顺序和逆序读起来完全一样的串叫做回文串。比如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都是回文串。
标签:printf put des style 自动机 应该 部分 长度 blog
一行由小写英文字母组成的字符串S。
样例说明
从第二个字符开始的字符串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; }
标签:printf put des style 自动机 应该 部分 长度 blog
原文地址:http://www.cnblogs.com/zzmmm/p/7138017.html