题面
题意
给出一个回文串,求相邻两个回文串的最长长度之和.
做法
像这样涉及两个回文串的关系的题目,都可以考虑正着和反着分别加入回文自动机,预处理出以每个点为左右端点的最长回文串的长度,最后再枚举断点统计答案即可.
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 500100
using namespace std;
int n,last,tt=1,mx[N],ans,q[N],h[N];
char str[N];
struct Node
{
int fail,len,son[26];
void init()
{
fail=len=0;
memset(son,0,sizeof(son));
}
}node[N];
inline void add(int u)
{
int i,j,k,p,q,v=str[u]-'a';
for(;str[u]!=str[u-node[last].len-1];last=node[last].fail);
if(!node[last].son[v])
{
node[++tt].len=node[last].len+2;
for(k=node[last].fail;str[u]!=str[u-node[k].len-1];k=node[k].fail);
node[tt].fail=node[k].son[v];
node[last].son[v]=tt;
}
last=node[last].son[v];
}
int main()
{
int i,j;
scanf("%s",str+1);
n=strlen(str+1);
node[0].fail=1;
node[1].len=-1;
for(i=1;i<=n;i++)
{
add(i);
h[i]=node[last].len;
// cout<<h[i]<<" ";if(i==n) puts("");
}
for(i=0;i<=tt;i++) node[i].init();
node[0].fail=1;
node[1].len=-1;
tt=1,last=0;
reverse(str+1,str+n+1);
for(i=1;i<=n;i++)
{
add(i);
q[i]=node[last].len;
}
reverse(q+1,q+n+1);
// for(i=1;i<=n;i++) cout<<q[i]<<" ";puts("");
for(i=1;i<n;i++)
{
ans=max(h[i]+q[i+1],ans);
}
cout<<ans;
}