时间限制: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 }