• BZOJ 2342: 【SHOI2011】 双倍回文


    题目链接:双倍回文

      回文自动机第二题。构出回文自动机,那么一个回文串是一个“双倍回文”,当且仅当代表这个串的节点(u)顺着(fail)指针往上跳,可以找到一个节点(x)满足(2len_x=len_u)。当然还需要(len_u)是(4)的倍数。

      然后我们把(fail)树构出来,在上面(dfs)一遍就做完了。

      下面贴代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define maxn 500010
    
    using namespace std;
    typedef long long llg;
    
    char a[maxn];
    int l[maxn],s[maxn][26],f[maxn];
    int head[maxn],next[maxn],to[maxn];
    int tt,la,ans,dt;
    bool w[maxn];
    
    void add(int c,int n){
    	int p=la;
    	while(a[n-l[p]-1]!=a[n]) p=f[p];
    	if(!s[p][c]){
    		int np=++tt,k=f[p]; l[np]=l[p]+2;
    		while(a[n-l[k]-1]!=a[n]) k=f[k];
    		f[np]=s[k][c]; s[p][c]=np;
    	}
    	la=s[p][c];
    }
    
    void link(int x,int y){to[++dt]=y;next[dt]=head[x];head[x]=dt;}
    void dfs(int u){
    	if(~l[u]&1) w[l[u]]=1;
    	if(l[u]%4==0 && w[l[u]>>1]) ans=max(ans,l[u]);
    	for(int i=head[u];i;i=next[i]) dfs(to[i]);
    	w[l[u]]=0;
    }
    
    int main(){
    	File("a");
    	l[++tt]=-1; f[0]=1;
    	int n;scanf("%d %s",&n,a+1);
    	for(int i=1;i<=n;i++) add(a[i]-'a',i);
    	for(int i=tt;i>1;i--) link(f[i],i);
    	dfs(1); dfs(0); printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    Javascript 返回上一页
    html中link和import方式导入CSS文件的区别
    Leecode no.76 最小覆盖子串
    Leecode no.344 反转字符串
    Leecode no.167 两数之和 II 输入有序数组
    Leecode no.567 字符串的排列
    遍历目录和文件信息
    JAVASCRIPT显示农历的日历
    asp.net上传图片加水印(c#)
    asp.net XML操作类
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6527173.html
Copyright © 2020-2023  润新知