题目描述见原题。
分析
首先这题用其他方法做也可行,但manacher应该是最优方法了。
设一个Lmax[i],表示从i开始算上i向左的最大回文串长度;设一个Rmax[i]表示从i开始算上i最大回文串长度。如果能处理出这两个东西就可以直接出答案。
首先可以在求每个点的最长回文半径时初步求出上述两个数组,然后进行递推。
Lmax是一个点往左扩展,越靠右越可能长,所以做逆推;Rmax是一个点往右扩展,越靠左越可能长,所以做顺推。递推式子见代码。
处理好之后扫一遍就出解了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN=100005;
int N=0,Lmax[MAXN*2],Rmax[MAXN*2],p[MAXN*2];
char s[MAXN*2],a[MAXN];
int main()
{
scanf("%s",a);
int len=strlen(a),i,mid=0,maxright=0;
s[N]='$';s[++N]='#';
for(i=0;i<len;i++) s[++N]=a[i],s[++N]='#';
for(i=1;i<=N;i++)
{
p[i]=maxright>i?min(p[mid*2-i],maxright-i):1;
while(s[i+p[i]]==s[i-p[i]]) p[i]++;
if(i+p[i]-1>maxright)maxright=i+p[i]-1,mid=i;
Lmax[i+p[i]-1]=max(Lmax[i+p[i]-1],p[i]-1); //初步求出两个数组
Rmax[i-p[i]+1]=max(Rmax[i-p[i]+1],p[i]-1);
}
int ans=0;
for(i=1;i<=N;i+=2) Rmax[i]=max(Rmax[i],Rmax[i-2]-2);
for(i=N;i>=1;i-=2) Lmax[i]=max(Lmax[i],Lmax[i+2]-2);
for(i=1;i<=N;i++) ans=max(ans,Lmax[i]+Rmax[i]);
cout<<ans;
return 0;
}