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


    描述

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

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

    parants树上拓扑

    合并endpos

     1 #pragma GCC optimize(2)
     2 #pragma G++ optimize(2)
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<iostream>
     7 #include<cstdio>
     8 #include<queue>
     9 
    10 #define N 2000007
    11 using namespace std;
    12 inline int read()
    13 {
    14     int x=0,f=1;char ch=getchar();
    15     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    16     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    17     return x*f;
    18 }
    19 
    20 int n;
    21 char s[N];
    22 struct sam
    23 {
    24     int last,cnt,rt;
    25     int c[N][26],fa[N],mx[N],endpos[N];
    26     sam(){last=cnt=rt=1;}
    27     void extend(int x)
    28     {
    29         int p=last,np=last=++cnt;mx[np]=mx[p]+1,endpos[np]=1;
    30         while(p&&!c[p][x])
    31         {
    32             c[p][x]=np;
    33             p=fa[p];
    34         }
    35         if(!p)fa[np]=rt;
    36         else
    37         {
    38             int q=c[p][x];
    39             if(mx[q]==mx[p]+1)fa[np]=q;
    40             else
    41             {
    42                 int nq=++cnt;mx[nq]=mx[p]+1;
    43                 memcpy(c[nq],c[q],sizeof(c[q]));
    44                 fa[nq]=fa[q];
    45                 fa[q]=fa[np]=nq;
    46                 while(c[p][x]==q)c[p][x]=nq,p=fa[p];
    47             }
    48         }
    49     }
    50     int du[N],now=1,pre=0;queue<int>q[2];
    51     void init_endpos()
    52     {
    53         memset(du,0,sizeof(du));
    54         for (int i=cnt;i>1;i--)
    55             du[fa[i]]++;
    56         for (int i=1;i<=cnt;i++)
    57             if(!du[i])q[pre].push(i),du[i]=-1;
    58         while(!q[pre].empty())
    59         {
    60             while(!q[pre].empty())
    61             {
    62                 int x=q[pre].front();q[pre].pop();
    63                 endpos[fa[x]]+=endpos[x];
    64                 du[fa[x]]--;
    65                 if(!du[fa[x]])q[now].push(fa[x]);
    66             }
    67             swap(pre,now);
    68         }
    69     }
    70     int ans[N];
    71     void solve()
    72     {
    73         memset(ans,0,sizeof(ans));
    74         for (int i=1;i<=cnt;i++)
    75             ans[mx[i]]=max(ans[mx[i]],endpos[i]);
    76         for (int i=n-1;i>=1;i--)
    77             ans[i]=max(ans[i],ans[i+1]);
    78         for (int i=1;i<=n;i++)
    79             printf("%d
    ",ans[i]);
    80     }
    81 }sam;
    82 
    83 int main()
    84 {
    85     scanf("%s",s+1),n=strlen(s+1);
    86     for (int i=1;i<=n;i++)
    87         sam.extend(s[i]-'a');
    88     sam.init_endpos();
    89     sam.solve();
    90 }
  • 相关阅读:
    C/C++程序员必备的15个编辑器和集成开发环境
    天猫浏览型应用的CDN静态化架构演变
    实用技巧:如何用 CSS 做到完全垂直居中
    JavaScript 字符串操作:substring, substr, slice
    Hybrid App 开发初探:使用 WebView 装载页面
    引领潮流!最顶尖的24个获奖网页作品
    HTML5编程之旅系列一:HTML5 Geolocation 初探
    JavaScript 秘密花园——对象的使用和属性操作
    提高效率!15款最好的 Bug 跟踪应用程序
    最常用的8款 PHP 调试工具,你用过吗?
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8503928.html
Copyright © 2020-2023  润新知