Manacher algorithm, known as "horse car" algorithm, can solve the problem of the length of the longest palindromic substring of a string at the time complexity is O (n) case.
First, the general solution palindromic substring
Two, Manacher algorithm based on the concept
1, the radius of the array radius palindrome
![](https://img2018.cnblogs.com/blog/1589483/201909/1589483-20190901000903107-1472052871.webp)
2, the right border of the rightmost R palindrome
A position right border of the rightmost palindrome palindrome refers to the sub-location and location prior to this series, the rightmost place of arrival. For example, a string # a # c # b # b # c # b # d # s #, each seeking its position as follows:
Rightmost palindrome right boundary of R process
The very beginning R = -1, the p = 0 position, that is its own palindrome, the palindrome rightmost right boundary R = 0; when p = 1, there is a palindromic sequence # a #, R = 2; p = 2, R = 2; P = the time 3, R = 6; when p = 4, the right border of the rightmost palindromic or right margin of p = 3, R = 6, and so on.
3, the right border of the rightmost palindromic symmetry center C
Right border is rightmost palindromic above-mentioned center point C, as shown below, when p = 4, R = 6, C = 3
Third, the process Manacher algorithm
First major aspects divided into two cases:
The first case: the next position to be moved to the right of the rightmost right border R of the palindrome.
For example, in the beginning, R = -1, p, next to a moved position p = 0, p = 0 at R = -1 on the right; = 0, R = 0 at this time, the p-p at a shift position is p = 1, also R = 0 on the right.
In this case, a common solution, the moved position of the center of symmetry, spread to both sides, while the update array radius palindrome, the palindrome center of symmetry of the rightmost and rightmost right border R palindromic right boundary C.
The second case: move to the next position is the most right-palindrome right boundary of R or R on the left
In this case it is divided into three types:
1, to move to the next position p1 is not the rightmost palindromic right boundary the right R, and cL <pL.
C p1 to p2 is the center of symmetry point of symmetry;
pL is the center of symmetry of p2 palindromic substring left border;
cL is the center of symmetry C of the left border palindromic substring.
P1 palindromic radius in this case is the palindromic radius p2 radius [p2].
2, moved to the next position p1 ticket is not the rightmost palindromic right of the right boundary of R, and cL> pL.
C p1 to p2 is the center of symmetry point of symmetry;
pL is the center of symmetry of p2 palindromic substring left border;
cL is the center of symmetry C of the left border palindromic substring.
Palindrome radius p1 p1 is in this case to the distance R R-p1 + 1.
3, next to a moved position p1 ticket is not the rightmost palindromic right of the right boundary of R, and cL = pL;
C p1 to p2 is the center of symmetry point of symmetry;
pL is the center of symmetry of p2 palindromic substring left border;
cL is the center of symmetry C of the left border palindromic substring.
Palindrome radius R and C. update on p1 will continue to expand out of this situation, but then just out from R to expand it, expand after
Four, Manacher time complexity analysis
From the above analysis, it can be seen, the time required for a location palindromic radius of the second case 2 is a complexity of O (1), the first case and the second case 3, when R is a constantly expanding outwardly, will not retreat back and find palindromic radius R of the position is not within the judgment, and so the entire string, R is moved from a moving start point string to the end, the time complexity is O (n), so the whole time complexity is manacher O (n).
Five, Manacher of code implementation
#include<iostream> #include<vector> using namespace std; int Manacher(string str){ int str_len = str.size(); vector<char> tmp; tmp.push_back('$'); int len[2*str_len]; for(int i = 1;i < str_len;i++){ tmp.push_back('#'); tmp.push_back(str[i]); } tmp.push_back('#'); for(char i : tmp) cout << i; cout << endl; int mx = 0; int max_len = -1; int mid = 0, pos = 0; for(int i = 1; tmp[i]; i++) { if(i < mx) len[i] = min(len[2*mid-i],mx-i); else len[i] = 1; while(tmp[i-len[i]] == tmp[i+len[i]]) len[i]++; if(len[i]+i > mx){ mx = len[i]+i; mid = i; } if(max_len <= len[i]-1) { max_len = len[i]-1; pos = i; } // maxlen = max(maxlen,len[i]-1); } for(int i=pos-max_len; i<pos+max_len; ++i) { if (tmp[i] != '#') cout << tmp[i]; } cout << endl; return max_len; } int main(){ string str; cin >> str; cout << Manacher(str); return 0; }