链接:点击打开链接
题意:顺序和逆序读起来完全一样的串叫做回文串。比如是回文串,而不是(的顺序为abc,逆序为,不相同)。输入长度为的串,求的最长双回文子串,即可将分为两部分,, 且和都是回文串。
代码:
#include<bits/stdc++.h>
using namespace std;
const int siz=100005;
char s[siz<<1],S[siz<<1];
int a[siz<<1],ll[siz<<1],rr[siz<<1];
void manacher(int len){
int i,id,mx,ans;
id=mx=ans=0;
for(i=0;i<len;i++){
if(i<mx)
a[i]=min(a[(id<<1)-i],mx-i);
else
a[i]=1;
while(s[i-a[i]]==s[i+a[i]])
a[i]++;
if(i+a[i]>mx){
id=i;
mx=i+a[i];
}
ll[i+a[i]-1]=max(ll[i+a[i]-1],a[i]-1); //求回文的同时维护ll和rr
rr[i-a[i]+1]=max(rr[i-a[i]+1],a[i]-1);
}
}
int main(){
int i,ans,len;
scanf("%s",S);
s[0]='$',s[1]='#';
len=2;
for(i=0;S[i];i++){
s[len++]=S[i];
s[len++]='#';
}
s[len++]='#'; //ll[i]为以i结尾的最长回文长度
memset(ll,0,sizeof(ll)); //rr[i]为以i为开始的最长回文长度
memset(rr,0,sizeof(rr));
manacher(len);
for(i=len-3;i>=0;i-=2)
ll[i]=max(ll[i],ll[i+2]-2);
for(i=3;i<len;i+=2) //求出每个点的回文长度后递推出所有的点
rr[i]=max(rr[i],rr[i-2]-2); //的最大值
ans=0;
for(i=3;i<len;i+=2){ //枚举#号作为分界点
if(ll[i]!=0&&rr[i]!=0)
ans=max(ans,ll[i]+rr[i]);
}
printf("%d\n",ans);
return 0;
}