We need to make the string s into a palindrome by only adding characters to the front, using as few added characters as possible.
When we prepend characters, only the front of s is free to change. The tail of s stays fixed, so for the whole result to be a palindrome, the longest prefix of s that is already a palindrome can stay where it is. Everything after that prefix has to be mirrored in front. In "aacecaaa", the prefix "aacecaa" is a palindrome. The leftover suffix is "a", so prepending one "a" gives "aaacecaaa".
The problem reduces to finding the longest palindromic prefix of s. Once we have its length k, the answer is reverse(s[k..]) + s.
A direct scan checks each palindromic prefix one at a time, which costs O(n^2). For a string up to 50,000 characters that is too slow, so the optimal approaches reframe the search as a prefix-suffix matching problem (KMP) or a hash comparison (rolling hash).
0 <= s.length <= 5 * 10^4 → With n up to 50,000, an O(n^2) approach performs up to 2.5 billion character comparisons, too slow within typical time limits. The target is O(n).s consists of lowercase English letters only → Plain character comparisons, no Unicode handling.Try every prefix of s, starting from the longest, and check if it is a palindrome. The first palindrome found while scanning from longest to shortest is the longest palindromic prefix.
Once that prefix has length k, the characters from index k to the end are the part that is not yet mirrored. Reversing that suffix and prepending it produces the palindrome.
We start from the longest prefix because a longer palindromic prefix leaves a shorter suffix to mirror, and a shorter suffix means a shorter result.
n down to 1:s[0..k-1] is a palindrome by comparing characters from both ends.s[k..n-1].s.This is too slow for large inputs because it rechecks overlapping prefixes from scratch. The next approach finds the longest palindromic prefix in a single linear pass by reframing it as a prefix-suffix match.
Finding the longest palindromic prefix of s is equivalent to finding the longest prefix of s that also appears as a suffix of reverse(s).
The reason: a prefix s[0..k-1] is a palindrome exactly when it reads the same forward and backward, so it equals its own reverse. The reversed string rev ends with the reverse of that prefix, which is the prefix itself. So the palindromic prefix of s is both a prefix of s and a suffix of rev.
The KMP failure function computes, for each position, the longest proper prefix of the string up to that point that is also a suffix. Building combined = s + "#" + reverse(s) and computing its failure table makes the final entry the length of the longest palindromic prefix of s.
The # separator is a character that does not occur in s. It stops any matched prefix-suffix from spanning the boundary between s and reverse(s). Without it the failure value at the end could exceed n, which would not correspond to any prefix of s.
s is empty, return "".rev = reverse of s.combined = s + "#" + rev.combined:fail[i] = length of the longest proper prefix of combined[0..i] that is also a suffix.fail[0] = 0.i from 1 to end:j = fail[i-1].j > 0 and combined[i] != combined[j], set j = fail[j-1].combined[i] == combined[j], increment j.fail[i] = j.fail[len(combined) - 1] gives the length of the longest palindromic prefix.s after that prefix, reverse it, and prepend to s.The KMP approach is exact and allocates a failure table plus two extra strings. The next approach reaches the same O(n) time with O(1) working memory by comparing rolling hashes instead of building the failure table, at the cost of a small collision probability.
Maintain two rolling hashes while scanning s: one for the current prefix read forward, one for the same prefix read backward. When both hashes are equal at position i, the prefix s[0..i] reads the same in both directions, so it is a palindrome (subject to the collision caveat below).
Scan left to right, updating both hashes by one character at each step. Each time the forward and backward hashes are equal, record i + 1 as the current best palindromic-prefix length. The last recorded length is the longest one, and it gives the answer.
The forward hash treats the prefix as the polynomial s[0]*base^i + s[1]*base^(i-1) + ... + s[i], which is the value of the prefix read left to right. The backward hash builds s[0] + s[1]*base + ... + s[i]*base^i, which is the value of the prefix read right to left. The two are equal as integers precisely when the prefix is a palindrome.
Comparing them modulo a large prime can in principle report a false match between two different strings (a hash collision). With a 64-bit-safe modulus the probability is negligible for these inputs, but it is not a proof. The KMP approach is the choice when an exact guarantee is required.
forwardHash = 0, backwardHash = 0, power = 1, and bestLen = 0.i from 0 to n-1:forwardHash by appending s[i]: forwardHash = forwardHash * base + s[i].backwardHash by prepending s[i]: backwardHash = backwardHash + s[i] * power.power = power * base.forwardHash == backwardHash, record bestLen = i + 1.s[bestLen..], reverse it, and prepend to s.