zoukankan      html  css  js  c++  java
  • HihoCoder1445 后缀自动机二·重复旋律5

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

    现在小Hi想知道一部作品中出现了多少不同的旋律?

    输入

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

    输出

    一行一个整数,表示答案。

    题解:

    题目意思就是让你求有多少种不同的子串。

    后缀自动机的板题。理解后缀自动机的longest[]数组,对于每一个状态s,它的等价类集合中的子串数量即为 l[s]-l[fa[s]];然后答案就是把每一个状态的的数量累加;

    (原因就是任意两个等价类交集为空)

    参考代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    char s[maxn];
    int len;
    int T;
    struct SAM{
        int last,cnt,nxt[maxn*2][26],fa[maxn*2],l[maxn*2];
        long long ans;
        void init()
        {
            last = cnt=1;
            memset(nxt[1],0,sizeof nxt[1]);
            fa[1]=0;ans=0;l[1]=0;
        }
        int inline newnode()
        {
            ++cnt;
            memset(nxt[cnt],0,sizeof nxt[cnt]);
            fa[cnt]=l[cnt]=0;
            return cnt;
        }
        void add(int c)
        {
            int p=last;
            int np=newnode();
            last=np;
            l[np]=l[p]+1;
            while(p&&!nxt[p][c])
            {
                nxt[p][c]=np;
                p = fa[p];
            }
            if(!p) fa[np]=1;
            else
            {
                int q = nxt[p][c];
                if(l[q]==l[p]+1) fa[np] = q;
                else
                {
                    int nq = newnode();
                    memcpy(nxt[nq],nxt[q],sizeof nxt[q]);
                    fa[nq] = fa[q];
                    l[nq] = l[p]+1;
                    fa[np]=fa[q]=nq;
                    while (nxt[p][c]==q)
                    {
                        nxt[p][c]=nq;
                        p=fa[p];
                    }
                }
            }
            ans+=(l[last]-l[fa[last]])*1ll;
        }
        void query()
        {
            int l=1,r=strlen(s+1);
            //scanf("%d%d",&l,&r);
            init();
            for(int i=l;i<=r;i++) add(s[i]-'a');
            printf("%lld
    ",ans);
        }
    }sam;
    int main()
    {
        scanf("%s",s+1);
        sam.query();
        return 0;
    } 
    View Code
  • 相关阅读:
    Tire树的理解和应用
    C语言:socket简单模拟http请求
    C语言:关于socket的基础知识点
    php中的ip2long和long2ip的理解
    理解php中的pack/unpack/ord/chr
    zlog学习笔记(mdc)
    计算机工作的进行
    期末总结
    第十四周学习报告
    第十三周学习报告
  • 原文地址:https://www.cnblogs.com/csushl/p/10805025.html
Copyright © 2011-2022 走看看