题解
这题可以马拉车水过。拿回文自动机来做一做也是一样的。
li
l
i
表示以第i个字符为末位置的字符串前缀的最大回文后缀。
ri
r
i
表示以第i个字符为首位置的字符串后缀的最大回文前缀。
那么就正着反着各做一遍回文自动机。
注意这里struct两个就好了,千万不要省空间第二遍memset用同一个数组,貌似我
O(n∗26)
O
(
n
∗
26
)
就TLE了。还debug了许久。
另外注意
求答案就
O(n)
O
(
n
)
遍历一遍取max。
写回文自动机一定要注意一点!
在增量时,一定要在建完
fail[now]
f
a
i
l
[
n
o
w
]
以后再把
ch[last][alp]
c
h
[
l
a
s
t
]
[
a
l
p
]
设为
now
n
o
w
,
不然会死循环QWQ
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int ans,n,l[N],r[N];
char s[N];
struct P{
int cnt,ch[N][26],p,f[N],len[N];
inline int new_node(int m)
{
len[cnt]=m;return cnt++;
}
inline int get_fail(int x,int m)
{
for(;s[m-len[x]]!=s[m+1];)
x=f[x];
return x;
}
inline void insert(int alp,int m,int op)
{
p=get_fail(p,m);
if(!ch[p][alp]){
int now=new_node(len[p]+2);
f[now]=ch[get_fail(f[p],m)][alp];
ch[p][alp]=now;
}
p=ch[p][alp];
if(!op) l[m+1]=len[p];
else r[n-m]=len[p];
}
}A,B;
int main(){
int i;
scanf("%s",s+1);n=strlen(s+1);
A.new_node(0);A.new_node(-1);A.f[0]=1;
for(i=1;i<=n;++i) A.insert(s[i]-'a',i-1,0);
B.new_node(0);B.new_node(-1);B.f[0]=1;
reverse(s+1,s+n+1);
for(i=1;i<=n;++i) B.insert(s[i],i-1,1);
for(i=1;i<n;++i)
ans=max(ans,l[i]+r[i+1]);
printf("%d\n",ans);
}