P3805 【模板】manacher 算法 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目很简单:
给出一个只由小写英文字符 a~z 组成的字符串 S ,求 S 中最长回文串的长度 。
字符串长度为 n(1≤n≤1.1e7)
不过考虑到n很大,所以靠暴力求肯定超时,所以要用到马拉车算法(manacher算法)
如图,mid是i~r的回文中心,因此以t为回文中心的字符串=以t的对称点为回文中心的字符串,所以p[t]可以等于p[2*mid-t]。但是由于超过r的部分(即右红边部分)不能保证等于左红边的部分,所以p[t]的长度不能超过r-t,这样就得出了manacher算法中核心语句:
p[t]=min(p[mid*2-t],r-t+1) //这里+1是因为p[t]存的半径包含了对称中心
#include<bits/stdc++.h>
using namespace std;
const int MAX=1.5e7+10;
char s[MAX<<1]; //s存处理后的字符串
int p[MAX<<1],cnt=0,ans; //p[t]存以t为对称中心的回文串的最大半径
void conduct(){
char c=getchar();
s[0]='~';
s[++cnt]='|';
while((c>='a'&&c<='z') || (c>='A'&&c<='Z'))
s[++cnt]=c,s[++cnt]='|',c=getchar();
}
int main(){
conduct();
for(int t=1,r=0,mid=0;t<=cnt;++t){
//r和mid分别代表最靠右的回文串的右边界和对称中心
if(t<=r) p[t]=min(p[mid*2-t],r-t+1);
while(s[t-p[t]]==s[t+p[t]]) p[t]++; //向两侧拓展
if(p[t]+t>r) r=p[t]+t-1,mid=t; //更新r和mid
if(p[t]>ans) ans=p[t];
}
cout << ans-1;
return 0;
}