kZjPBD.jpg

后缀自动机三·重复旋律6

时间限制:15000ms
单点时限:3000ms
内存限制:512MB

描述

小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。

现在小Hi想知道一部作品中所有长度为K的旋律中出现次数最多的旋律的出现次数。但是K不是固定的,小Hi想知道对于所有的K的答案。

解题方法提示

输入

共一行,包含一个由小写字母构成的字符串S。字符串长度不超过 1000000。

输出

共Length(S)行,每行一个整数,表示答案。

样例输入
aab
样例输出
2
1
1





 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 2*1e6+10;
 4 
 5 
 6 int last =1,tot=1;
 7 struct NODE 
 8 {
 9     int ch[26];
10     int len,fa;
11     long long  maxlen=0;
12     NODE () {memset(ch,0,sizeof ch); len=fa=0;}
13 
14 }dian[maxn];
15 long long  cnt[maxn];
16 int nn=0;
17 inline void add(int c)
18 {
19    int p = last; int np = last = ++tot; 
20    dian[np].maxlen=1; // 这种点包含了一个后缀,所以比他所有的儿子多1,maxlen设为一 
21    dian[np].len = dian[p].len+1;
22    for( ; p && !dian[p].ch[c]; p=dian[p].fa)dian[p].ch[c] = np;
23 
24    if(!p) dian[np].fa = 1,cnt[1]++;
25    else 
26    {
27     //   cout<<"HERE"<<endl;
28        int q=dian[p].ch[c];
29        if(dian[q].len == dian[p].len+1)dian[np].fa=q,cnt[q]++;
30        else
31        {
32            int nq=++tot;
33            dian[nq]=dian[q]; 
34            dian[nq].maxlen=0;// 注意这一步,直接复制点的话,要把maxlen清零
35            //一开始没注意到这里,wa无数次 
36            dian[nq].len=dian[p].len+1;
37            dian[q].fa=dian[np].fa=nq;
38            cnt[nq]+=2;
39            for(;p&&dian[p].ch[c]==q;p=dian[p].fa)dian[p].ch[c]=nq;
40        }
41    }
42 
43 }
44 long long  ans[maxn];
45 
46 int topsort()
47 {
48       queue<int > q;
49       for(int i=1;i<=tot;i++)if(!cnt[i])q.push(i);
50       while(!q.empty())
51       {
52            int t=q.front(); q.pop();
53            dian[dian[t].fa].maxlen += dian[t].maxlen;
54            if(--cnt[dian[t].fa] == 0)q.push(dian[t].fa);
55       }
56       // 整个就是向上的递推 
57       
58       for(int i=1;i<=tot;i++)ans[dian[i].len] = max(ans[dian[i].len],dian[i].maxlen );
59       for(int i=nn-1;i>=1;i--)ans[i] = max(ans[i],ans[i+1]);
60       for(int i=1;i<=nn;i++)cout<<ans[i]<<endl;
61       
62 }
63 
64 
65 signed main()
66 {
67     string s;cin>>s; int len=s.length();  nn =len;
68     for (int i=0;i<len;i++)add(s[i]-'a');
69   //  for(int i=1;i<=tot;i++)cout<<dian[i].maxlen<<" ";
70     topsort();
71 }

 



posted @ 2019-04-28 12:49  Through_The_Night  阅读(182)  评论(0编辑  收藏  举报