• bzoj 2342: [Shoi2011]双倍回文


    Description

    Input

    输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。

    Output

    输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0

    Sample Input

    16
    ggabaabaabaaball

    Sample Output

    12

    HINT

    N<=500000

    Source

    第二道回文自动机的题了...

    这道题就是找沿着fail找到能找到一个点使len[u]==2*len[u]&&len[u]%4==0;

    按fail连边之后,在fail树上dfs即可(可以对len开一个桶)

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=600050;
    int gi()
    {
      int x=0,flag=1;
      char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
      return x*flag;
    }
    int len[N],nxt[N][30],fail[N],cnt[N],last,tt;
    int head[N],nxt2[N],to[N],cnt2,l,num[N],ans;
    char s[N];
    void insert(int c,int n){
        int cur=last;
        while(s[n-len[cur]-1]!=s[n]) cur=fail[cur];
        if(!nxt[cur][c]){
    	int now=++tt,la=fail[cur];len[now]=len[cur]+2;
    	while(s[n-len[la]-1]!=s[n]) la=fail[la];
    	fail[now]=nxt[la][c],nxt[cur][c]=now;
        }
        last=nxt[cur][c];cnt[last]++;
    }
    void lnk(int x,int y){
        to[++cnt2]=y,nxt2[cnt2]=head[x],head[x]=cnt2;
    }
    void dfs(int x){
        if(len[x]%4==0&&num[len[x]/2]) ans=max(ans,len[x]);
        num[len[x]]--;
        for(int i=head[x];i;i=nxt2[i]) dfs(to[i]);
        num[len[x]]++;
    }
    int main(){
        l=gi();len[++tt]=-1;fail[0]=1;
        scanf("%s",s+1);
        for(int i=1;i<=l;i++) insert(s[i]-'a',i);
        for(int i=1;i<=tt;i++) lnk(fail[i],i);
        dfs(0);printf("%d
    ",ans);
    }
    
  • 相关阅读:
    批处理
    命名规则
    注释
    HTML DOM属性
    OLTP
    修改HTML元素
    HTML
    工具资源系列之给虚拟机装个centos
    工具资源系列之给虚拟机装个windows
    工具资源系列之给mac装个虚拟机
  • 原文地址:https://www.cnblogs.com/qt666/p/6916764.html
Copyright © 2020-2023  润新知