双倍回文[Shoi2011][bzoj2342]
2342: [Shoi2011]双倍回文
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2820 Solved: 1088
[Submit][Status][Discuss]
Description
Input
输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。
Output
输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0。
Sample Input
16
ggabaabaabaaball
ggabaabaabaaball
Sample Output
12
HINT
N<=500000
Source
题意就是要求一个回文串,这个回文串的一半也是回文串,那么,可以看出这个串的长度必须是4的倍数。。。。。真心想不出,想了30分钟,并没有做出来,对回文自动机的理解还不是很充分,看了题解,大部分用了马拉车,思维题,但也有充分利用回文自动机的性质;观察回文自动机上的fail链,也就是后缀链,它满足fail链连向的节点是这个节点最长的回文后缀,那么,当整个串都添加进去时,fail链也就成了fail树,连接了所有本质不同的回文串,而且,这个是一个有向的,由小的串往两边添加字符成大的串,所以就可以从根节点0号节点开始dfs,记录一个桶,表示长度为i的节点在以前出现过,就只要判断这个串的长度%4==0,并且长度为len/2的节点在以前出现过,这样就很好的解决了这个问题;
主要是利用了fail链与fail树的性质,求出双倍回文!!
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<cmath> 6 #include<map> 7 #include"set" 8 #include"queue" 9 #include"vector" 10 #include"iomanip" 11 #include"cstring" 12 #define inf 1<<29 13 #define ll long long 14 #define re register 15 #define il inline 16 #define rep(i,a,b) for(register int i=a;i<=b;++i) 17 #define file(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 18 using namespace std; 19 const int N=26,MAXN=500010; 20 struct Edge{ 21 int to,net; 22 }e[MAXN]; 23 int ans; 24 int head[MAXN],num_e; 25 il void link(int x,int y) { 26 e[++num_e].to=y,e[num_e].net=head[x],head[x]=num_e; 27 } 28 struct Palindromic_Tree{ 29 int nxt[MAXN][N],fail[MAXN],len[MAXN],lst,n,p; 30 int S[MAXN]; 31 il int newnode(int l) { 32 for(re int i=0;i<N;++i) 33 nxt[p][i]=0; 34 len[p]=l; 35 return p++; 36 } 37 il void init() { 38 p=0; 39 newnode(0); 40 newnode(-1); 41 n=0;lst=0;S[0]=-1; 42 fail[0]=1; 43 } 44 il int get_fail(int x){ 45 while(S[n-len[x]-1]!=S[n]) x=fail[x]; 46 return x; 47 } 48 il void add(int c) { 49 c-='a'; 50 S[++n]=c; 51 int cur=get_fail(lst); 52 if(!nxt[cur][c]) { 53 int now=newnode(len[cur]+2); 54 fail[now]=nxt[get_fail(fail[cur])][c]; 55 nxt[cur][c]=now; 56 link(fail[now],now); 57 } 58 lst=nxt[cur][c]; 59 } 60 int T[MAXN]; 61 il void dfs(int x) { 62 if(len[x]%4==0&&T[len[x]/2]) ans=max(ans,len[x]); 63 T[len[x]]++; 64 for(int i=head[x];i;i=e[i].net) 65 dfs(e[i].to); 66 T[len[x]]--; 67 } 68 }Pam; 69 char ch[MAXN]; 70 inline int gi() { 71 re int res=0,f=1;re char ch=getchar(); 72 while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); 73 if(ch=='-') f=-1,ch=getchar(); 74 while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar(); 75 return res*f; 76 } 77 int main(){ 78 file("Y"); 79 int n=gi(); 80 scanf("%s",ch);int len=strlen(ch); 81 Pam.init(); 82 for(re int i=0;i<len;++i) Pam.add(ch[i]); 83 Pam.dfs(0); 84 cout<<ans; 85 return 0; 86 }