• HihoCoder1449 重复旋律6(后缀自动机)


    描述

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

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

    输入

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

    输出

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

    样例输入

    aab

    样例输出

    2
    1
    1

    1,很好的利用了拓扑。

    2,利用了单调性。

      for(i=tot;i>0;i--){
            ans[i]=max(ans[i],ans[i+1]);
        }

    2017-11-24 代码是舶来品,参考hihocoder,等把后缀自动机消化了自己再写一遍吧。

    2017-11-25 这几个题理解得差不多了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<string>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int N=1e6+100;
    const int M=1e6+5;
    int tot,slink[2*N],trans[2*N][26],minlen[2*N],maxlen[2*N],edpts[2*N],n;
    char str[2*N];
    int blue[2*N],ind[2*N],ans[2*N+10];
    int newstate(int _maxlen,int _minlen,int* _trans,int _slink) {
        maxlen[++tot]=_maxlen;
        minlen[tot]=_minlen;
        slink[tot]=_slink;
        if(_trans)
            for(int i=0; i<26; i++)
                trans[tot][i]=_trans[i];
        return tot;
    }
    int add(char ch,int u) {
        int c=ch-'a',v=u;
        int z=newstate(maxlen[u]+1,-1,NULL,0);
        blue[z]=1;//绿色 
        while(v&&!trans[v][c]) {
            trans[v][c]=z;
            v=slink[v];
        }
        if(!v) {
            minlen[z]=1;
            slink[z]=1;
            ind[0]++;
            return z;
        }
        int x=trans[v][c];
        if(maxlen[v]+1==maxlen[x]) {
            slink[z]=x;
            minlen[z]=maxlen[x]+1;
            ind[x]++;
            return z;
        }
        int y=newstate(maxlen[v]+1,-1,trans[x],slink[x]);
        slink[z]=slink[x]=y;
        ind[y]+=2;
        minlen[x]=minlen[z]=maxlen[y]+1;
        while(v&&trans[v][c]==x) {
            trans[v][c]=y;
            v=slink[v];
        }
        minlen[y]=maxlen[slink[y]]+1;
        return z;
    }
    void count() {
        queue<int> q;
        for( int i=1; i <=tot; i++ )if( !ind[i] ) {
                q.push(i);
            }
        while( !q.empty() ) {
            int u = q.front();
            q.pop();
            if(blue[u] ) edpts[u]++;
            edpts[ slink[u]] += edpts[u];
            if( !--ind[slink[u]] ) q.push(slink[u]);
        }
    }
    
    int main() {
        int i;
        scanf("%s",str);
        int len=strlen(str),pre=1;
        tot=1;
        for(i=0; i<len; i++) {
            pre=add(str[i],pre);
        }
        count();
        for(i=0;i<=tot;i++){
            ans[maxlen[i]] = max(ans[maxlen[i]],edpts[i]);
        }
        for(i=tot;i>0;i--){
            ans[i]=max(ans[i],ans[i+1]);
        }
        for(i=1;i<=len;i++)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    python的input获取用户输入
    pyinstaller打包成功的.exe,本机运行正常,在别的电脑上运行报错Failed to execute script ...
    Shell应用:批量将文件编码由gbk转utf8
    不伤眼睛的文字背景色 豆沙绿RGB值为(199,237,204)
    javascript禁用backspace回退,shift+backspace前进,F5等刷新页面功能
    crontab实行shell乱码问题解决
    linux C 函数大全 .
    Web服务器:shell字符串处理
    Linux C编程一站式学习 .
    crontab中date的用法
  • 原文地址:https://www.cnblogs.com/hua-dong/p/7889684.html
Copyright © 2020-2023  润新知