O (n) palindrome substring (manacher) algorithm
Transferred from: http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html
Data source network See: http://www.felix021.com/blog/read.php?2040
Problem Description:
Enter a string to find the largest palindrome substring in the list. The meaning of a substring is: a string fragment that appears consecutively in the original string. The meaning of a palindrome is: look and look backwards, like Abba and Yyxyy.
Analytical:
The O (n) palindrome string (manacher) algorithm is introduced here
The basic point of the algorithm: first, in a very ingenious way, all possible odd/even length palindrome strings are converted to odd lengths: Insert a special symbol on either side of each character. For example, Abba becomes #a #b#b#a#, ABA becomes #a #b#a#. To further reduce the complexity of the encoding, you can add another special character at the beginning of the string, so that you do not have to deal with cross-border issues specifically, such as $ #a #b#a#.
The following is an example of string 12212321, which, after the previous step, became s[] = "$ #1 #2#2#1#2#3#2#1#";
Then use an array of p[i] to record the length (including S[i]) of the longest palindrome string centered on the character S[i], such as the corresponding relationship of S and P:
S # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 #
P 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1
(as you can see, P[i]-1 is exactly the total length of the palindrome string in the original P.S)
The following calculation P[i], the algorithm adds two auxiliary variable ID and MX, where the ID represents the largest palindrome substring center position, MX is id+p[id], that is, the maximum palindrome substring boundary.
The key point of this algorithm is here: if mx > I, then p[i] >= MIN (p[2 * id-i], mx-i).
The specific code is as follows:
if (mx > i) {
// P[i] = MIN (p[2 * id-i], mx-i);
P[i] = (P[2*id-i] < (mx-i) P[2*id-i]: (Mx-i));} Else { 1;}
When Mx-i > P[j], the palindrome string centered on S[j] is contained in a palindrome string centered on S[id], because I and J are symmetric, the palindrome string centered on s[i] is necessarily contained in a palindrome string centered on S[id], so there must be p[i] = P[j], see.
When P[j] > mx-i, the palindrome string centered on s[j] is not completely contained in a palindrome string centered on S[id], but based on symmetry, it is known that the part surrounded by the two green boxes is the same, that is, the palindrome string centered on the s[i], and its right will expand to the position of MX at least. , which means p[i] >= mx-i. As to whether the post-MX part is symmetrical, it is only one match.
For the case of MX <= i, p[i] can not be made more assumptions, only p[i] = 1, and then to match the
The following gives the original text, further explaining the reason for the linearity of the algorithm
Source:
#include <iostream>#include<string>#include<cstring>UsingNamespace std;voidFINDBMSTR (string&str) { int*p =New int[Str.size () +1]; Memset (P,0,sizeof(p));//Key Parts//The ID indicates the location of the center of the maximum palindrome substring, and MX is id+p[id], which is the boundary of the maximum palindrome substring. int mx = 0, id = 0; for(inti =1; I <= str.size (); i++) { if(MX >i) {P[i]= (p[2*id-i] < (mx-i)? p[2*id-i]: (MX-i)); } Else{P[i]=1; } while(Str[i-p[i]] = = Str[i +P[i]]) P[i]++; if(i + p[i] >mx) {mx= i +P[i]; ID=i; } } //find the largest p[i], that is, the maximum palindrome length intMax =0, II; for(inti =1; I < str.size (); i++) { if(P[i] >max) {II=i; Max=P[i]; }} Max--;//Print Palindrome intStart = II-Max; intEnd = II +Max; for(inti = start; I <= end; i++) { if(Str[i]! ='#') {cout<<Str[i]; }} cout<<Endl; Deletep;}intMain () {stringstr ="12212321"; stringSTR0; STR0+="$#"; for(inti =0; I < str.size (); i++) {STR0+=Str[i]; STR0+="#"; } cout<< STR0 <<Endl; Findbmstr (STR0); Return0;}
Execution Result:
Turn: Manacher algorithm----O (n) time to find the maximum palindrome substring