KMP trick
Time O(n) Space O(n)t = s + "#" + reverse(s); L = lps of t's last position = longest palindromic prefix. Answer = reverse(s.substring(L)) + s.
s = "aacecaaa"Step 1/4Join s, a separator '#', and s reversed. A start of s that is a palindrome shows up again at the end of the reversed part.
class Solution {
public String shortestPalindrome(String s) {
String rev = new StringBuilder(s).reverse().toString();
String t = s + "#" + rev;
int[] lps = new int[t.length()];
for (int i = 1, len = 0; i < t.length(); ) {
if (t.charAt(i) == t.charAt(len)) lps[i++] = ++len;
else if (len > 0) len = lps[len - 1];
else lps[i++] = 0;
}
int keep = t.isEmpty() ? 0 : lps[t.length() - 1];
return rev.substring(0, s.length() - keep) + s;
}
}Verdict: The separator stops matches crossing the middle.