• SPOJ 8222 NSUBSTR


    http://www.spoj.com/problems/NSUBSTR/

    题意:

    F(x)定义为字符串S中所有长度为x的子串重复出现的最大次数

    输出F[1]~F[len(S)]

    用字符串S构建后缀自动机

    若子串 str ∈状态s,那么子串str 在字符串S中出现的次数就是| Right(s) |

    显然不能枚举所有状态的所有子串

    但是我们可以线性的时间得到F[Max(s)]= | Right(s) |

    然后再对F做一个后缀最大值即可

    如何得到 一个状态Right集合的大小?

    一个状态s的Right集合就是Parent树上,s的子树中叶子节点Right集合的并集

    所以可以 从parent树上 底层向上层更新,即将底层节点的Right并入父节点的Right

    这个可以通过拓扑排序实现 

    #include<cstdio>
    #include<cstring>
    
    #define N 250002
    
    #define max(x,y) ((x)>(y) ? (x) : (y))
    
    char s[N];
    
    int tot=1,fa[N<<1],len[N<<1],ch[N<<1][26];
    int last=1,p,np,q,nq;
    
    int front[N<<1],nxt[N<<1],to[N<<1],cnt;
    
    int r[N<<1],f[N];
    int v[N<<1],sa[N<<1];
    
    void extend(int c)
    {
        len[np=++tot]=len[last]+1;
        for(p=last;p && !ch[p][c]; p=fa[p]) ch[p][c]=np;
        if(!p) fa[np]=1;
        else
        {
            q=ch[p][c];
            if(len[q]==len[p]+1) fa[np]=q;
            else
            {
                len[nq=++tot]=len[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[nq]));
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
            }
        }
        last=np;
    }
    
    int main()
    {
        scanf("%s",s+1);
        int n=strlen(s+1);
        for(int i=1;i<=n;++i) 
        {
            r[tot+1]=1;
            extend(s[i]-'a');
        }
        for(int i=1;i<=tot;++i) v[len[i]]++;
        for(int i=1;i<=n;++i) v[i]+=v[i-1];
        for(int i=1;i<=tot;++i) sa[v[len[i]]--]=i;
        for(int i=tot;i;--i) r[fa[sa[i]]]+=r[sa[i]];
        for(int i=1;i<=tot;++i) f[len[i]]=max(f[len[i]],r[i]);
        for(int i=n-1;i;--i) f[i]=max(f[i],f[i+1]); 
        for(int i=1;i<=n;++i) printf("%d
    ",f[i]);
    }
  • 相关阅读:
    Java 8特性
    11成最多体积的容器
    MySQL数据库理解
    java范型
    ArrayList源码分析
    1.面试题
    jvm简单了解
    121. 买卖股票的最佳时机
    有效的括号
    java如何判断一个字符串中某个字符有几个
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8575878.html
Copyright © 2020-2023  润新知