讲解:
https://www.jianshu.com/p/392172762e55
https://blog.csdn.net/qq_43456058/article/details/94588721
模板代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e6+5;
int len, p[2 * N];
char s[N], str[2 * N];
void init() {
len = strlen(s);
int k = 0;
str[k++] = '$';///str【0】
for(int i = 0; i < len; i++) {
str[k++] = '#';
str[k++] = s[i];///一个#,一个字符
}
str[k++] = '#';///str[2*len+1]
len = k;
str[k]='@';///字符串尾,防止越界
}
int manacher() {
int sum = 0, mx = 0, id;///mx为最右边,id为中心点
for(int i = 1; i < len; i++)
{
if(i < mx) p[i] = min(mx - i, p[2 * id - i]);///判断这个点有没有超过mx
else p[i] = 1;///超过就标记为1
while(str[i - p[i]] == str[i + p[i]]) p[i]++;///判断当前点是不是最长回文子串,不断的向右扩展
if(p[i] + i > mx)///p[i]+i 为最右边界
{
mx = p[i] + i;
id = i;///更新中间点
}
sum = max(sum, p[i] - 1);///最长回文串长度
}
return sum;
}
int main() {
while(~scanf("%s", s)) {
init();
printf("%d\n", manacher());
}
return 0;
}
模拟版代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e6+5;
int len, p[2 * N];
char s[N], str[2 * N];
void init() {
len = strlen(s);
int k = 0;
str[k++] = '$';///str【0】
for(int i = 0; i < len; i++) {
str[k++] = '#';
str[k++] = s[i];///一个#,一个字符
}
str[k++] = '#';///str[2*len+1]
len = k;
str[k]='@';///字符串尾,防止越界
for(int i=0;i<=k;i++)
{
cout<<str[i];
if(i>=10)cout<<" ";
else cout<<" ";
}
cout<<endl;
for(int i=0;i<=k;i++)
{
cout<<i<<" ";
}
cout<<endl;
}
int manacher() {
int sum = 0, mx = 0, id;///mx为最右边,id为中心点
for(int i = 1; i < len; i++)
{
cout<<"i "<<i<<" "<<"mx "<<mx<<endl;
if(i < mx) p[i] = min(mx - i, p[2 * id - i]);///判断这个点有没有超过mx
else p[i] = 1;///超过就标记为1
cout<<"一。"<<" "<<"i "<<i<<" "<<"p[i] "<<p[i]<<endl;
while(str[i - p[i]] == str[i + p[i]]) p[i]++;///判断当前点是不是最长回文子串,不断的向右扩展
cout<<"二。"<<" "<<"i "<<i<<" "<<"p[i] "<<p[i]<<endl;
if(p[i] + i > mx)///p[i]+i 为最右边界
{
mx = p[i] + i;
id = i;///更新中间点
cout<<"更新";
}
cout<<"三。"<<" "<<"id "<<id<<" "<<"mx "<<mx<<endl;
sum = max(sum, p[i] - 1);///最长回文串长度
cout<<"最长回文串长度--"<<sum<<endl;
for(int j=0;j<=len;j++)
{
cout<<str[j];
if(j>=10)cout<<" ";
else cout<<" ";
}
cout<<endl;
for(int j=0;j<=len;j++)
{
cout<<j<<" ";
}
cout<<endl;
for(int j=0;j<=len;j++)
{
cout<<p[j]<<" ";
}
cout<<endl<<endl;
}
return sum;
}
int main() {
while(~scanf("%s", s)) {
init();
printf("%d\n", manacher());
}
return 0;
}
运行结果:
cabbaf
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
i 1 mx 0
一。 i 1 p[i] 1
二。 i 1 p[i] 1
更新三。 id 1 mx 2
最长回文串长度--0
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
i 2 mx 2
一。 i 2 p[i] 1
二。 i 2 p[i] 2
更新三。 id 2 mx 4
最长回文串长度--1
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 0 0 0 0 0 0 0 0 0 0 0 0
i 3 mx 4
一。 i 3 p[i] 1
二。 i 3 p[i] 1
三。 id 2 mx 4
最长回文串长度--1
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 0 0 0 0 0 0 0 0 0 0 0
i 4 mx 4
一。 i 4 p[i] 1
二。 i 4 p[i] 2
更新三。 id 4 mx 6
最长回文串长度--1
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 0 0 0 0 0 0 0 0 0 0
i 5 mx 6
一。 i 5 p[i] 1
二。 i 5 p[i] 1
三。 id 4 mx 6
最长回文串长度--1
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 0 0 0 0 0 0 0 0 0
i 6 mx 6
一。 i 6 p[i] 1
二。 i 6 p[i] 2
更新三。 id 6 mx 8
最长回文串长度--1
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 0 0 0 0 0 0 0 0
i 7 mx 8
一。 i 7 p[i] 1
二。 i 7 p[i] 5
更新三。 id 7 mx 12
最长回文串长度--4
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 0 0 0 0 0 0 0
i 8 mx 12
一。 i 8 p[i] 2
二。 i 8 p[i] 2
三。 id 7 mx 12
最长回文串长度--4
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 0 0 0 0 0 0
i 9 mx 12
一。 i 9 p[i] 1
二。 i 9 p[i] 1
三。 id 7 mx 12
最长回文串长度--4
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 0 0 0 0 0
i 10 mx 12
一。 i 10 p[i] 2
二。 i 10 p[i] 2
三。 id 7 mx 12
最长回文串长度--4
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 2 0 0 0 0
i 11 mx 12
一。 i 11 p[i] 1
二。 i 11 p[i] 1
三。 id 7 mx 12
最长回文串长度--4
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 2 1 0 0 0
i 12 mx 12
一。 i 12 p[i] 1
二。 i 12 p[i] 2
更新三。 id 12 mx 14
最长回文串长度--4
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 2 1 2 0 0
i 13 mx 14
一。 i 13 p[i] 1
二。 i 13 p[i] 1
三。 id 12 mx 14
最长回文串长度--4
$ # c # a # b # b # a # f # @
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 2 1 2 1 2 5 2 1 2 1 2 1 0
4