zoukankan      html  css  js  c++  java
  • 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]);
    }
  • 相关阅读:
    数组的typedef 和函数的typedef
    函数返回值当左值的问题
    C++中虚析构函数的作用
    word2013密钥
    子类父类步长问题
    函数重定义——重写———重载
    C++的成员初始化列表和构造函数体(以前未知)
    常引用
    项目开发中的字符串模型
    指针函数的++(极易犯错误)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8575878.html
Copyright © 2011-2022 走看看