• 洛谷 P3804 【模板】后缀自动机 统计单词出现次数


    后缀自动机模板题.

    关键时求解每个节点的 $right$ 大小.

    由于后缀自动机在构建时会保证点和点的 $right$ 只可能没有交集,或者一个是另一个的真子集,我们可以不重复的对 $right$ 进行统计与更新.

    从长度大的子串向前更新,沿着 $parent$ 跳即可.

    最后再枚举一下.

    Code:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define setIO(s) freopen(s".in","r",stdin)
    #define maxn 3000000
    #define N 30 
    #define ll long long
    using namespace std;
    int last=1,tot=1,n; 
    int ch[maxn][N],cnt[maxn],f[maxn],dis[maxn],rk[maxn]; 
    ll C[maxn],ans; 
    char str[maxn]; 
    struct Suffix_Automaton{
        void ins(int c){
            int p=last,np=++tot; last=np; dis[np]=dis[p]+1; 
            while(p&&!ch[p][c])ch[p][c]=np,p=f[p];
            if(!p) f[np]=1;
            else{
                int q=ch[p][c],nq;  
                if(dis[q]==dis[p]+1) f[np]=q;
                else{
                    nq=++tot; 
                    dis[nq]=dis[p]+1;
                    memcpy(ch[nq],ch[q],sizeof(ch[q]));
                    f[nq]=f[q],f[q]=f[np]=nq;
                    while(p&&ch[p][c]==q) ch[p][c]=nq,p=f[p]; 
                } 
            }
            cnt[last]=1; 
        }
    }sam; 
    int main(){
        //setIO("input");
        scanf("%s",str),n=strlen(str);
        for(int i=0;i<n;++i) sam.ins(str[i]-'a'); 
        for(int i=1;i<=tot;++i) ++C[dis[i]]; 
        for(int i=1;i<=tot;++i) C[i]+=C[i-1];  
        for(int i=1;i<=tot;++i) rk[C[dis[i]]--]=i;
        for(int i=tot;i>=1;--i){
            int p=rk[i];
            cnt[f[p]]+=cnt[p];
            if(cnt[p]>1) ans=max(ans,(ll)cnt[p]*dis[p]); 
        }
        printf("%lld",ans); 
        return 0;
    }
    

      

  • 相关阅读:
    luogu P1451 求细胞数量
    P1443 马的遍历
    luogu P1194 买礼物
    codevs 4919 线段树练习4
    printf的实型
    printf的整型
    scanf
    printf
    c++常用函数
    字符类型C++(ascll码表)
  • 原文地址:https://www.cnblogs.com/guangheli/p/10290339.html
Copyright © 2020-2023  润新知