[LeetCode] Shortest Palindrome
The idea is to find the longest palindromic substring of s
that begins with s[0]
. Then take the remaining susbtring, reverse it and append it to the beginning of s
.
For example, given s = "aacecaaa"
, the longest palindromic substring beginning with s[0] = 'a'
is "aacecaa"
and the remaining substring is "a"
. Reverse it and append it to the beginning of s
gives "aaacecaaa"
.
For s = "abcd"
, the longest palindromic substring beginning with s[0] = 'a'
is "a"
and the remaining substring is "bcd"
. Reverse it and append it to the beginning of s
gives "dcbabcd"
.
The most difficult part is to implement the Manacher's algorithm to find the longest palindromic substring starting with s[0]
. Please refer to this nice article if you want to know how it works.
The code is as follows.
1 class Solution { 2 public: 3 string shortestPalindrome(string s) { 4 string t = process(s); 5 int n = t.length(), center = 0, right = 0; 6 int* palin = new int[n]; 7 for (int i = 1; i < n - 1; i++) { 8 int i_mirror = 2 * center - i; 9 palin[i] = (right > i) ? min(palin[i_mirror], right - i) : 0; 10 while (t[i + palin[i] + 1] == t[i - palin[i] - 1]) 11 palin[i]++; 12 if (i + palin[i] > right) { 13 center = i; 14 right = i + palin[i]; 15 } 16 } 17 int pos; 18 for (int i = n - 2; i; i--) { 19 if (i - palin[i] == 1) { 20 pos = palin[i]; 21 break; 22 } 23 } 24 string tail = s.substr(pos); 25 reverse(tail.begin(), tail.end()); 26 return tail + s; 27 } 28 private: 29 string process(string& s) { 30 int n = s.length(); 31 string t(2 * n + 3, '#'); 32 t[0] = '$'; t[2 * n + 2] = '%'; 33 for (int i = 0; i < n; i++) 34 t[2 * (i + 1)] = s[i]; 35 return t; 36 } 37 };
Note that this part of the code is just to find the ending position of the longest palindromic substring begining with s[0]
.
1 int pos; 2 for (int i = n - 2; i; i--) { 3 if (i - palin[i] == 1) { 4 pos = palin[i]; 5 break; 6 } 7 }