zoukankan      html  css  js  c++  java
  • 后缀自动机三·重复旋律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 }


  • 相关阅读:
    [机器学习案例1]基于KNN手写数字识别
    Android横竖屏切换View设置不同尺寸或等比例缩放的XML解决方案
    Qt之网络编程
    Redis系列-存储篇sorted set主要操作函数小结
    Code First Migrations更新数据库结构的具体步骤
    json文件解析
    go语言文件操作
    docker容器与主机之间的文件复制
    ubuntu16.04 安装docker
    Go语言string,int,int64 ,float之间类型转换方法
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10783309.html
Copyright © 2011-2022 走看看