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 substrings are converted to odd lengths :
Inserts a special symbol on both sides 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, its ID represents the largest palindrome substring center position, MX is id+p[id], that is, the boundary of the largest palindrome substring.
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] = (P[2*id-i] < (mx-i) P[2*id-i]: (Mx-i));} else{ P[i] = 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>using namespace std;void findbmstr (string & str) {int *p = new Int[str.size () + 1]; memset (p, 0, sizeof (p)); int mx = 0, id = 0; for (int i = 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; }} int max = 0, ii; for (int i = 1; i < str.size (); i++) {if (P[i] > max) {II = i; max = P[i]; }} max--; int start = Ii-max; int end = II + max; for (int i = start; I <= end; i++) {if (str[i]! = ' # ') {cout << str[i]; }} cout << Endl; Delete p;} int main () {string str = "12212321"; String str0; STR0 + = "$#"; for (int i = 0; i < str.size (); i++) {str0 + = Str[i]; STR0 + = "#"; } cout << str0 << Endl; Findbmstr (STR0); return 0;}
Execution Result:
Introduction to Algorithms: Palindrome substring (manacher) algorithm, O (n) Time efficiency realization