标签:let hit 题目 更新 for long 自动 blank nbsp
题目大意
求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串
建两个回文自动机,一个维护前缀,一个维护后缀
最后扫一遍更新答案
My complete code:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
const LL maxn=200000;
struct node{
LL son[26],fail,len;
}tree1[maxn],tree2[maxn];
LL last,nod1,nod2,len,ans;
LL belong1[maxn],belong2[maxn];
char s1[maxn],s2[maxn];
inline void solve1(){
s1[0]=‘#‘;
tree1[0].fail=1; tree1[0].len=0;
tree1[1].fail=0; tree1[1].len=-1;
last=0;
nod1=1;
for(LL i=1;i<=len;++i){
while(s1[i-tree1[last].len-1]!=s1[i])
last=tree1[last].fail;
if(!tree1[last].son[s1[i]]){
tree1[++nod1].len=tree1[last].len+2;
LL j=tree1[last].fail;
while(s1[i-tree1[j].len-1]!=s1[i])
j=tree1[j].fail;
tree1[nod1].fail=tree1[j].son[s1[i]];
tree1[last].son[s1[i]]=nod1;
}
last=tree1[last].son[s1[i]];
belong1[i]=tree1[last].len;
}
}
inline void solve2(){
s2[0]=‘#‘;
tree2[0].fail=1; tree2[0].len=0;
tree2[1].fail=0; tree2[1].len=-1;
last=0;
nod2=1;
for(LL i=1;i<=len;++i){
while(s2[i-tree2[last].len-1]!=s2[i])
last=tree2[last].fail;
if(!tree2[last].son[s2[i]]){
tree2[++nod2].len=tree2[last].len+2;
LL j=tree2[last].fail;
while(s2[i-tree2[j].len-1]!=s2[i])
j=tree2[j].fail;
tree2[nod2].fail=tree2[j].son[s2[i]];
tree2[last].son[s2[i]]=nod2;
}
last=tree2[last].son[s2[i]];
belong2[len-i+1]=tree2[last].len;
}
}
int main(){
scanf(" %s",s1+1);
len=strlen(s1+1);
for(LL i=1;i<=len;++i){
s1[i]-=‘a‘;
s2[len-i+1]=s1[i];
}
solve1();
solve2();
for(LL i=1;i<len;++i)
if(belong1[i]+belong2[i+1]>ans)
ans=belong1[i]+belong2[i+1];
printf("%lld",ans);
return 0;
}/*
baacaabbacabb
12
*/
标签:let hit 题目 更新 for long 自动 blank nbsp
原文地址:https://www.cnblogs.com/y2823774827y/p/10100253.html