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
  • 相关阅读:
    钱多多软件制作04
    团队项目01应用场景
    HDU 4411 arrest
    HDU 4406 GPA
    HDU 3315 My Brute
    HDU 3667 Transportation
    HDU 2676 Matrix
    欧拉回路三水题 POJ 1041 POJ 2230 POJ 1386
    SPOJ 371 BOXES
    POJ 3422 Kaka's Matrix Travels
  • 原文地址:https://www.cnblogs.com/csushl/p/10805025.html
Copyright © 2011-2022 走看看