Detailed Algorithm
The Manacher algorithm can solve the longest palindrome substring in linear time. It can be said that the implementation is very clever. His basic idea is that the extension of the palindrome substring from the middle to both sides must be the same, so first we need to perform certain operations on the string. Preprocessing:
For example: String: aaaa aba
Then their lengths are even and odd respectively, because if it is even, we can't find a midpoint to make both sides the same, so we add a non-appearing character between every two characters to make them all odd :
#a#a#a#a# #a#b#a# This will definitely find the midpoint of a longest palindrome
We let p[i] , which means that the point i is the center, can be extended to the rightmost length, maxlen means: the farthest distance that can be extended (traversing all points, the longest distance that can be extended)
Now we have to traverse the string from the beginning to calculate p[i], and use p[i] to continuously update maxlen, so because we added '#', our final answer is maxlen-1
Suppose that our current traversal position is k+i, and i in all points before k is the farthest distance extended, that is, maxlen = p[i]
The latter situation is divided into two types:
1) When k+i > maxlen, we cannot find a point corresponding to this point, then initialize p[k+i] = 1, and then traverse from this point to both sides to find the longest palindrome string:
while(s[k + p[k+i]] == s[k - s[k+i]) p[k+i]++;
2) When k+i < maxlen
①When the left end of the palindrome and the corresponding point ik is greater than the left end of i
In this case, the length of our p[i+k] must be the length from i+k to the right endpoint of i, that is: p[i+k] = p[i] - k, because if it is longer, then the length of i The length must be more than the current length, it can still be extended to the right
②When the left end of the palindrome and the corresponding point ik is greater than the left end of i
Then p[i+k] = p[ik]
③ When the left end of the palindrome and the corresponding point ik is equal to the left end of i
At this time, p[i+k] must be greater than or equal to p[ik], and then we need to continue to judge while(s[i+k+p[i+k]] == s[i+k - p[ik]] ) p[i+k] ++;
We can conclude that:
p [i + k] = min (p [i] - k, p [i - k]); while(s[i+k+p[i+k]] == s[i+k - p[i-k]] ) p[i+k] ++;
Then traversing to the end of the string can solve the final answer
Chestnuts & Templates
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int N = 110000 + 10; intmain() { char s[N*2]; int p[N*2]; while(~scanf("%s",s)) { int len = strlen(s); for(int i = len;i >= 0;i --) { s[i+i+2] = s[i]; s[i+i+1] = '#'; } s[0] = '*'; int maxlen = 0,id = 0; for(int i = 2;i < len*2+1 ;i ++) { if(p[id]+id > i) p[i] = min(p[id*2-i] , p[id] + id - i); else p[i] = 1; while(s[i + p[i]] == s[i - p[i]]) p[i] ++; if(p[id]+id < p[i]+i) id = i; if(maxlen < p[i]) maxlen = p[i]; } printf("%d\n",maxlen-1); } return 0; }