BZOJ2565:最长双回文串
2565: 最长双回文串
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2195 Solved: 1119
[Submit][Status][Discuss]
Description
顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Input
一行由小写英文字母组成的字符串S。
Output
一行一个整数,表示最长双回文子串的长度。
Sample Input
baacaabbacabb
Sample Output
12
HINT
样例说明
从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。
对于100%的数据,2≤|S|≤10^5
思路{
首先应该建出回文自动机,那么我们可以很自然地想到在插入字符的过程中统计当前插入的字符的长度(因为回文自动机保证了当前插入的字符串是能匹配的最长长度)。
但是还要反向搞一下即可。
}
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf (1<<30) #define il inline #define RG register #define LL long long #define maxx 100010 using namespace std;char s[maxx]; int nxt[maxx][27],len[maxx],f[maxx],l,cc,Maxpre[maxx],Maxnxt[maxx]; void Insert(int n,int c,int p[]){ int P=l;while(s[n-len[P]-1]!=s[n])P=f[P]; if(!nxt[P][c]){ len[++cc]=len[P]+2; int p=f[P]; while(s[n-len[p]-1]!=s[n])p=f[p]; f[cc]=nxt[p][c],nxt[P][c]=cc; }l=nxt[P][c];p[n]=len[l]; }char t[maxx]; void work(){ f[0]=1,len[++cc]=-1; scanf("%s",s+1);int L=strlen(s+1); for(RG int i=1;i<=L;++i)Insert(i,s[i]-'a',Maxpre);l=cc=0; memset(nxt,0,sizeof(nxt));memset(len,0,sizeof(len));memset(f,0,sizeof(f)); f[0]=1,len[++cc]=-1; for(RG int i=1;i<=L;++i)t[L-i+1]=s[i];for(int i=1;i<=L;++i)s[i]=t[i]; for(RG int i=1;i<=L;++i)Insert(i,s[i]-'a',Maxnxt);LL Ans=0; for(RG int i=1;i<=L;++i)Ans=max(Ans,(LL)Maxnxt[i]+Maxpre[L-i]);printf("%lld",Ans); } int main(){ freopen("1.in","r",stdin); // freopen("1.out","w",stdout); work();return 0; }