Original article: http://www.cnblogs.com/BigBallon/p/3816890.html
Only for the record study, not for plagiarism!
http://www.felix021.com/blog/read.php?2040
For the manacher algorithm, the primary function is to find the longest palindrome substring of a string.
The algorithm's time complexity book is linear, i.e. O (n)
I'll tell you in two parts below.
1) pretreatment
The subtlety of this algorithm is to subtly avoid considering whether the length of the palindrome string is odd or even (if you do not know what a palindrome number, palindrome string, please self-Baidu)
In the Manacher algorithm, we need to pre-preprocess our original string, where the original string is called S1, the preprocessing string is called S2.
So, for S1 = "Ababba",
S2 = "$ #a #b#a#b#b#a#" after preprocessing.
In this way, all palindrome strings, in the S2, are odd, you can draw a picture yourself or take a look. Note here that we will s2[0] = ' $ ', which is another character that does not appear in a string, in order to avoid crossing the array when it is accessed. If there is no such treatment. This behavior may occur in the code p[i] = min (p[2*id]-i), mx-i):
When you proceed to the second loop, at this point i=1,id = 0,2*id-i =-1, an array out of bounds occurs: So this processing is necessary.
So the preprocessing code is probably like this:
void Init () { int i, j = 2; S2[0] = ' $ ', s2[1] = ' # '; for (i=0;s1[i];i++) { s2[j++] = s1[i]; S2[j++] = ' # '; } S2[J] = ' + ';}
2) Manacher algorithm
After the preprocessing is completed, the longest palindrome string can be obtained by using the Manacher algorithm.
You will find that all string-related algorithms are very focused on using the useful information left over from the previous matching process, but this algorithm is not an exception.
First, there is an auxiliary array p[] (for S2), which records the maximum number of characters that extend to the left and right in P[i], including p[i] itself. Think about it and you'll see that p[i]-1 represents the length of the most palindrome substring in the corresponding position in the original string.
Referring to the contents of the previous article, following the example of string 12212321, the previous step has changed to s[] = "$ #1 #2#2#1#2#3#2#1#", and then an array p[i] is used to record the length of the left/right expansion of the longest palindrome string centered on the character S[i] (including s[i) , which is the length of the "fold" of the palindrome, such as the correspondence between 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----- ----------------------------------------------------(P.S. Can be seen, p[i]-1 is exactly the total length of the palindrome in the original string)
To see how to match and use useful information, here we use a variable ID to record the expansion length position information, with the variable MX record the extension length at the ID location.
First give the code, in combination with the code
void Manacher (char* s) { int i, id = 0, mx = 0; P[0] = 0; P[0] Position no use for (i=1;s[i];i++) //String for linear scan { if (mx > i) //If MX is larger than current I, it is divided into two cases, Detailed to see the article at the beginning of the recommended blog diagram, the very force of the figure p[i] = min (p[2*id-i],mx-i); else //If MX is smaller than I, there is no information available, then you can only start from scratch match p[i] = 1; while (S[i + p[i]] = = S[i-p[i]]) p[i]++; Match if (MX < p[i] + i)//persist if there is an update MX as well as ID { mx = p[i] + i; id = i;}} }
Then there are several topics:
1. HDU 3068 Longest palindrome
Test instructions: There is nothing to say in Chinese. Template title, used to learn very well
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace Std;
#define MAXN 222222
#define CLR (A, B) memset (A,b,sizeof (a))
int P[MAXN];
Char S1[MAXN],S2[MAXN];
void Manacher (char* s)
{
int i, id = 0, mx = 0;
P[0] = 0;
for (int i=1;s[i]!= ' n '; i++)
{
if (mx > i)
P[i] = min (p[2*id-i],mx-i);
Else
P[i] = 1;
while (S[i + p[i]] = = S[i-p[i]]) p[i]++;
if (i + p[i] > mx)
{
MX = i + p[i];
id = i;
}
}
}
void init (char* s1,char*s2)
{
S2[0] = ' $ ';
int i = 0;
int j = 1;
for (i=0;s1[i]!= ' n '; i++)
{
S2[j++] = ' # ';
S2[j++] = S1[i];
}
S2[j++] = ' # ';
S2[J] = ' + ';
}
void LG ()
{
int res = 0;
for (int i=0;s2[i]!= ' n '; i++)
res = max (res,p[i]);
printf ("%d\n", res-1);
}
int main ()
{
while (~SCANF ("%s", S1))
{
Init (S1,S2);
Manacher (S2);
LG ();
}
return 0;
}
#include <cstdio> #include <cstring> #include <algorithm>using namespace std; #define MAXN 222222 #define CLR (A, B) memset (A,b,sizeof (a)) int P[maxn];char s1[maxn],s2[maxn];void manacher (char* s) {int i, id = 0, mx = 0; P[0] = 0; for (int i=1;s[i]!= ' n '; i++) {if (mx > i) p[i] = min (p[2*id-i],mx-i); else p[i] = 1; while (S[i + p[i]] = = S[i-p[i]]) p[i]++; if (i + p[i] > mx) {mx = i + p[i]; id = i; }}}void Init (char* s1,char*s2) {s2[0] = ' $ '; int i = 0; int j = 1; for (i=0;s1[i]!= '; i++) {s2[j++] = ' # '; S2[j++] = S1[i]; } s2[j++] = ' # '; S2[J] = ' + ';} void lg () {int res = 0; for (int i=0;s2[i]!= ' n '; i++) res = max (res,p[i]); printf ("%d\n", res-1);} int main () {while (~SCANF ("%s", S1)) {init (S1,S2); Manacher (S2); LG (); } return 0;}
2. HDU 3294 Girls '
Test instructions: Find the longest palindrome substring and find the starting position.
Analysis: It will be pre-treatment, there is a pre-treatment, it is not difficult, anyway to deal with.
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace Std;
#define CLR (A, B) memset (A,b,sizeof (a))
#define MAXN 200020
int p[maxn<<1];
Char S1[MAXN], s2[maxn<<1];
int sta,end,res,id,ch;
void Manacher (char* s)
{
int i, id = 0, mx = 0;
P[0] = 0;
for (i=1;s[i];i++)
{
if (mx > i)
P[i] = min (p[2*id-i],mx-i);
Else
P[i] = 1;
while (S[i + p[i]] = = S[i-p[i]]) p[i]++;
if (MX < p[i] + i)
{
MX = p[i] + i;
id = i;
}
}
}
void Init ()
{
int i = 0, j, key = ' a '-ch;
for (i=0;s1[i];i++)
{
S1[i] + = key;
if (s1[i] > ' z ')
S1[i] = s1[i]-' z ' + ' a '-1;
if (S1[i] < ' a ')
S1[i] = ' z '-(' a '-s1[i]) + 1;
}
S2[0] = ' $ ', s2[1] = ' # ';
for (i=0,j=2;s1[i];i++)
{
S2[j++] = S1[i];
S2[j++] = ' # ';
}
S2[J] = ' + ';
}
void AC ()
{
GetChar ();
Init ();
Manacher (S2);
Res = 0, id = 0;
for (int i=0;s2[i];i++)
{
if (res < p[i])
{
res = p[i];
id = i;
}
}
if (Res < 3)
Puts ("No solution!");
Else
{
printf ("id =%d\n", id);
printf ("res =%d\n", res);
STA = ((id-res+2) >>1)-1;
End = sta + res-2;
printf ("%d%d\n", sta,end);
printf ("s1=%s, s2 =%s\n", s1,s2);
for (int i=sta;i<=end;i++)
printf ("%c", S1[i]);
Puts ("");
}
}
int main ()
{
while (~SCANF ("%c%s", &CH,S1))
{
AC ();
}
return 0;
}
#include <cstdio> #include <cstring> #include <algorithm>using namespace std; #define CLR (A, b) memset ( A,b,sizeof (a)) #define MAXN 200020int P[maxn<<1];char S1[MAXN], S2[maxn<<1];int sta,end,res,id,ch;void Manacher (char* s) {int i, id = 0, mx = 0; P[0] = 0; for (i=1;s[i];i++) {if (mx > i) p[i] = min (p[2*id-i],mx-i); else p[i] = 1; while (S[i + p[i]] = = S[i-p[i]]) p[i]++; if (MX < p[i] + i) {mx = p[i] + i; id = i; }}}void init () {int i = 0, j, key = ' a '-ch; for (i=0;s1[i];i++) {S1[i] + = key; if (s1[i] > ' z ') s1[i] = s1[i]-' z ' + ' a '-1; if (S1[i] < ' a ') s1[i] = ' z '-(' a '-s1[i]) + 1; } s2[0] = ' $ ', s2[1] = ' # '; for (i=0,j=2;s1[i];i++) {s2[j++] = S1[i]; S2[j++] = ' # '; } S2[j] = ' + ';} void AC () {GetChar (); Init (); Manacher (S2); Res = 0, id = 0; For(int i=0;s2[i];i++) {if (res < p[i]) {res = p[i]; id = i; }} if (res < 3) puts ("No solution!"); else {//printf ("id =%d\n", id); printf ("res =%d\n", res); STA = ((id-res+2) >>1)-1; End = sta + res-2; printf ("%d%d\n", sta,end); printf ("s1=%s, s2 =%s\n", s1,s2); for (int i=sta;i<=end;i++) printf ("%c", S1[i]); Puts (""); }}int Main () {while (~scanf ("%c%s", &ch,s1)) {AC (); } return 0;}
3. POJ 3974 palindrome
Test instructions: With HDU3068
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace Std;
#define CLR (A, B) memset (A,b,sizeof (a))
#define MAXN 1111111
int p[maxn<<1], cas = 1;
Char S1[MAXN], s2[maxn<<1];
void Manacher (char* s)
{
int mx = 0, I, id = 0;
P[0] = 0;
for (i=1;s[i];i++)
{
if (mx > i)
P[i] = min (p[2*id-i],mx-i);
Else
P[i] = 1;
while (S[i + p[i]] = = S[i-p[i]]) p[i]++;
if (MX < p[i] + i)
{
MX = p[i] + i;
id = i;
}
}
}
void Init ()
{
int I, j = 2;
S2[0] = ' $ ', s2[1] = ' # ';
for (i=0;s1[i];i++)
{
S2[j++] = S1[i];
S2[j++] = ' # ';
}
S2[J] = ' + ';
}
void AC ()
{
printf ("Case%d:", cas++);
int res = 0, i = 0;
for (i=0;s2[i];i++)
{
if (res < p[i])
res = p[i];
}
printf ("%d\n", res-1);
}
int main ()
{
while (~SCANF ("%s", S1))
{
if (strcmp ("END", s1) = = 0)
Break
Init ();
Manacher (S2);
AC ();
}
return 0;
}
#include <cstdio> #include <cstring> #include <algorithm>using namespace std; #define CLR (A, b) memset ( A,b,sizeof (a)) #define MAXN 1111111int p[maxn<<1], cas = 1;char S1[MAXN], s2[maxn<<1];void manacher (char* s) { int mx = 0, I, id = 0; P[0] = 0; for (i=1;s[i];i++) {if (mx > i) p[i] = min (p[2*id-i],mx-i); else p[i] = 1; while (S[i + p[i]] = = S[i-p[i]]) p[i]++; if (MX < p[i] + i) {mx = p[i] + i; id = i; }}} void init () {int I, j = 2; S2[0] = ' $ ', s2[1] = ' # '; for (i=0;s1[i];i++) {s2[j++] = S1[i]; S2[j++] = ' # '; } S2[j] = ' + ';} void AC () {printf ("Case%d:", cas++); int res = 0, i = 0; for (i=0;s2[i];i++) {if (res < p[i]) res = p[i]; } printf ("%d\n", res-1); }int Main () {while (~SCANF ("%s", S1)) {if (strcmp ("END", s1) = = 0) break; Init (); Manacher(S2); AC (); } return 0;}
4. HDU 4513 Story--Perfect Formation II
Test instructions: To find the longest palindrome substring, requirements: from the most middle of the palindrome to meet non-increment.
Analysis: Initially do not know how to solve, and then think about the Manacher function to add a judgment, and then a.
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace Std;
#define MAXN 100111
int p[maxn<<1], S1[MAXN], s2[maxn<<1];
int t,n;
void Manacher (int* s)
{
int id = 0, i, mx = 0;
P[0] = 0;
for (i=1;i<2*n+1;i++)
{
if (mx > i)
P[i] = min (p[2*id-i],mx-i);
Else
P[i] = 1;
while (S[i + p[i]] = = S[i-p[i]])
{
if (S[i + p[i]]! =-222)
{
if (S[i + p[i]] <= s[i + p[i]-2])
p[i]++;
Else
Break
}
p[i]++;
}
if (MX < i + p[i])
{
id = i;
MX = p[i] + i;
}
}
}
void Init ()
{
S2[0] = -111, s2[1] = 222;
int i = 0,J = 2;
for (i=0;i<n;i++)
{
S2[j++] = S1[i];
S2[j++] =-222;
}
}
void AC ()
{
scanf ("%d", &n);
for (int i=0;i<n;i++)
scanf ("%d", &s1[i]);
Init ();
Manacher (S2);
int ret =-1;
for (int i=0;i<2*n+1;i++)
{
if (P[i] > Ret)
ret = P[i];
}
printf ("%d\n", ret-1);
}
int main ()
{
scanf ("%d", &t);
while (t--)
{
AC ();
}
}
#include <cstdio> #include <cstring> #include <algorithm>using namespace std #define MAXN 100111int p[ MAXN<<1], S1[MAXN], S2[maxn<<1];int t,n;void manacher (int* s) {int id = 0, i, mx = 0; P[0] = 0; for (i=1;i<2*n+1;i++) {if (mx > i) p[i] = min (p[2*id-i],mx-i); else p[i] = 1; while (S[i + p[i]] = = S[i-p[i]) {if (s[i + p[i]]! = -222) {if (s[i + p[i]] & lt;= s[i + p[i]-2]) p[i]++; else break; } p[i]++; } if (MX < i + p[i]) {id = i; MX = p[i] + i; }}}void init () {s2[0] = -111, s2[1] =-222; int i = 0,J = 2; for (i=0;i<n;i++) {s2[j++] = S1[i]; S2[j++] =-222; }}void AC () {scanf ("%d", &n); for (int i=0;i<n;i++) scanf ("%d", &s1[i]); Init (); Manacher (S2); int ret =-1; for (int i=0;i<2*n+1;i++) {if (P[i] > ret) ret = p[i]; } printf ("%d\n", ret-1);} int main () {scanf ("%d", &t); while (t--) {AC (); }}
"Reprint" Manacher algorithm