• SPOJ


    You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of times that some string with length x appears in S. For example for string 'ababa' F(3) will be 2 because there is a string 'aba' that occurs twice. Your task is to output F(i) for every i so that 1<=i<=|S|.

    Input

    String S consists of at most 250000 lowercase latin letters.

    Output

    Output |S| lines. On the i-th line output F(i).

    Example

    Input:
    ababa

    Output:
    3
    2
    2
    1
    1

    依次输出“出现次数最多的长度为x的字符串”的出现次数 (1<=x<=n)

    后缀自动机

    建出后缀自动机,统计每个节点标记的长度的出现次数即可。注意要倒序更新,把子节点(长串)的值累加到fa结点(长串的子串)的值上。

      ↑建好后缀自动机以后,要用原串在自动机上跑一便,每一个到达结点的初始次数r置为1。刚开始傻傻地把所有节点的r都初始化成1了,导致统计错误(理解不透彻)

    顿悟:把后缀自动机的fa指针看成fail而不是father更直观 ←大概是我自己火星了)

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 using namespace std;
     8 const int mxn=500010;
     9 int read(){
    10     int x=0,f=1;char ch=getchar();
    11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 struct SAM{
    16     int t[mxn][26];
    17     int fa[mxn],l[mxn],r[mxn],rk[mxn];
    18     int S,cnt,last;
    19     int f[mxn],w[mxn];
    20     void init(){S=cnt=last=1;return;}
    21     void add(int c){
    22         int p=last,np=++cnt;last=np;
    23         l[np]=l[p]+1;
    24         for(;p && !t[p][c];p=fa[p])t[p][c]=np;
    25         if(!p){fa[np]=S;}
    26         else{
    27             int q=t[p][c];
    28             if(l[q]==l[p]+1){fa[np]=q;}
    29             else{
    30                 int nq=++cnt;l[nq]=l[p]+1;
    31                 memcpy(t[nq],t[q],sizeof t[q]);
    32                 fa[nq]=fa[q];
    33                 fa[np]=fa[q]=nq;
    34                 for(;p && t[p][c]==q;p=fa[p])t[p][c]=nq;
    35             }
    36         }
    37     }
    38     void st(char *s,int n){
    39 //        for(int i=1;i<=cnt;i++){r[i]=1;w[l[i]]++;}
    40         int p=S;
    41         for(int i=1;i<=n;i++){
    42             p=t[p][s[i]-'a'];
    43             r[p]++;
    44         }
    45         for(int i=1;i<=cnt;i++){w[l[i]]++;}
    46         for(int i=1;i<=n;i++)w[i]+=w[i-1];
    47         for(int i=1;i<=cnt;i++)rk[w[l[i]]--]=i;
    48         return;
    49     }
    50     void solve(int n){
    51         for(int i=cnt;i;i--){
    52             int t=rk[i];
    53             f[l[t]]=max(f[l[t]],r[t]);
    54             r[fa[t]]+=r[t];
    55         }
    56         for(int i=n-1;i;i--)f[i]=max(f[i],f[i+1]);
    57         return;
    58     }
    59 }sa;
    60 char s[mxn];
    61 int main(){
    62     int i,j;
    63     sa.init();
    64     scanf("%s",s+1);
    65     int len=strlen(s+1);
    66     for(i=1;i<=len;i++){
    67         sa.add(s[i]-'a');
    68     }
    69     sa.st(s,len);
    70     sa.solve(len);
    71     for(i=1;i<=len;i++)printf("%d
    ",sa.f[i]);
    72     return 0;
    73 }
  • 相关阅读:
    python学习笔记(4)装饰器
    python学习笔记(3)函数
    python学习笔记(2)集合
    python学习笔记(1)字典
    nginx.conf文件内容详解
    关于斐波拉契数列引出的迭代器生成器的一点讨论
    MAC电脑运行python并发编程遇到的问题
    docker 11 :私有仓库搭建
    docker 10 :docker单机网络模式
    【转】C#环形队列
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6420565.html
Copyright © 2020-2023  润新知