I. Description of the problem
Palindrome string and palindrome sequence are different:
SUBSTRING, be sure to continue
Sub sequence, not necessarily continuous
In fact, the longest palindrome string can be converted into LCS to do, the specific method is:
Generates a reverse string of the original string and then uses a DP to find the LCS for the original string and the reverse string
But this disadvantage is also obvious is O (n*n) complexity, even if optimized to: scrolling array + subscript to find the reverse string, also can not fundamentally solve the inefficiency of this algorithm.
If you want to solve the problem of palindrome string in O (n) time.
The answer is Manacher algorithm, using a sentence to generalize this algorithm:
Skip some useless comparisons by recording the most right position of the match and the corresponding symmetry center
In the following code, the right position for the match is MX, and the center of symmetry is the ID. second, Manacher algorithm template
Complete Template
int Manacher (string tmp) {
memset (p,0,sizeof (P));
int len=tmp.size ();
int k;
for (k=0;k<len;k++) {
S[2*k] = ' # ';
S[2*K+1] = Tmp[k];
}
S[2*k] = ' # ';
S[2*k+1] = ' the ';
Algorithm Core
Len=strlen (s);
int mx = 0; MX is recorded in the palindrome string before I, extending to the far right position
int id=0;//id Note the coordinate value for
(int i=0;i<len;++i) {
if (i < MX)//When the optimal MX is obtained Front optimal border left
p[i] = min (p[2*id-i],mx-i);
else
p[i]=1;
for (; S[i-p[i]] = = S[i+p[i]] && s[i-p[i]]!= ' and ' && s[i+p[i ']!= '////For calculations beyond MX or p[j ' boundaries
p[i]++ ;
if (P[i]+i > mx) {//current best case, update MX and id
mx = p[i] + i;//The most right case
id = I//note coordinate
}
}
int res = 0;
for (int i=0;i<len;++i) {
res = max (res,p[i]);
}
return res-1;
}
third, the algorithm thought
1, pretreatment
The algorithm inserts special characters between the beginning, end, and character of the string (here with ' # '), so that the odd palindrome string and even palindrome string are considered (uniformly odd), otherwise it will be troublesome to deal with palindrome string.
For example: The ABC becomes #a #b#c# so there are 7 characters.
ABCD becomes #a #b#c#d# has 9 characters.
There may be a doubt: preprocessing into this, not to calculate the length of the palindrome string, but also subtract these special characters.
In fact, because the algorithm uses p[i] to record the length of the longest single arm of this POS, such as #a #b#c#b#a# the length of this one-arm substring is #a #b#c, that is, the length is 6,
And here's a good property, P[i]-1 is the length of the palindrome string in the original string. namely ABCBA is 5 2, core algorithm
In fact, the core code of the Manacher algorithm is very simple, but the understanding is very subtle, it is true that the algorithm is written in the code of poetry .
Core code:
Algorithm Core
Len=strlen (s);
int mx = 0; MX is recorded in the palindrome string before I, extending to the far right position
int id=0;//id Note the coordinate value for
(int i=0;i<len;++i) {
if (i < MX)//at the current optimal Border left
p[i] = min (p[2*id-i],mx-i);//Calculate the symmetric initial value
else
p[i]=1;//If the MX boundary is exceeded, P[i] Initial value is 1 for
(; S[i-p[i]] = = S[i+p [i]] && S[i-p[i]] "!= ' && s[i+p[i]"!= '; )//For computations beyond the MX or p[j] boundary
p[i]++;
if (P[i]+i > mx) {//current best case, update MX and id
mx = p[i] + i;//Right-end case
id = I//note coordinates
}
}
The algorithm begins with an if else judgment to determine the initial value of the p[i].
The key point of the algorithm is here:
if (i < MX)///p[i]= min (p[2*id-i],mx-i) to the left of the current optimal boundary
;//Calculate the symmetric initial value
else
p[i]=1;//If the MX boundary is exceeded, P[i] The initial value is 1
Then why is min (p[2*id-i],mx-i)? 3.2.1 Take P[2*id-i], that is p[2*id-i] <= mx-i
In this case, the entire center I (or center J) of the substring is covered in the center of the ID, the length of Mx-id under the giant arm , due to the ID of the center of the complete symmetry, the inevitable p[j] = = P[i], 3.2.2 Take mx-i, that is p[2*id-i] &G t;= mx-i
In this case, the arm of the ID is not fully wrapped in the I-centric arm show when:
According to Symmetry, the two green boxes in the diagram are surrounded by the same, that is, the I-centric palindrome string, its right will expand at least to the MX position, that is, P[i] >= mx-i. As to whether the parts after MX are symmetric, you can only match one.
In addition, we should pay attention to the setting of "Sentinel", that is, to set special characters or "" "to represent the boundary, or the back of the
for (; S[i-p[i]] = = S[i+p[i]]; p[i]++);
Will go out of bounds.
Give me the original manuscript I drew.
In the figure below, when I is 13 o'clock, the arms show is greatest, but the p[i of this character is initialized to 6, i.e. I = 5 that point ' C '. reference materials
[1] http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html
[2] http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/