题目
正反两边PAM,记录每个位置向左延伸向右延伸的最长回文串的长度。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5,Max=26;
//记录一个以i为下标结尾得最长的字符串的长度
struct PAM{
int nex[N][26],fail[N],s[N],len[N],ans[N],las,tot,n;
int newnode(int le){
for(int i=0;i<Max;++i) nex[tot][i]=0;
len[tot]=le;
return tot++;
}
void init(){
tot=0,newnode(0),newnode(-1);
n=las=0,s[0]=-1,fail[0]=1;
}
int get_fail(int x){
while(s[n-len[x]-1]!=s[n]) x=fail[x];
return x;
}
void add(int c,int pos){
c-='a',s[++n]=c;
int cur=get_fail(las);
if(!nex[cur][c]){
int now=newnode(len[cur]+2);
fail[now]=nex[get_fail(fail[cur])][c];
nex[cur][c]=now;
}
las=nex[cur][c],ans[pos]=len[las];//以pos这个位置的最长后缀回文串的长度为len[las]。
}
}A,B;
char s[N];
int main(){
scanf("%s",s+1);int len=strlen(s+1);
A.init();
for(int i=1;i<=len;++i) A.add(s[i],i);//向左最长的后缀回文串
B.init();
for(int i=len;i>=1;--i) B.add(s[i],i);//向右最长的前缀回文串(倒过来就是后缀回文串哦)
int res=0;
for(int i=1;i<len;++i) res=max(res,A.ans[i]+B.ans[i+1]);
printf("%d\n",res);
}