• BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡 ——广义后缀自动机


    神奇的性质,叶子节点不超过20个。

    然后把这些节点提出来构成一颗新树,那么这些树恰好包含了所有的情况。

    所以直接广义后缀自动机。

    然后统计本质不同的字符串就很简单显然了。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
       
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define maxn 4000005
       
    struct Generalized_Suffix_Array{
        int cnt;
        int go[maxn][10],l[maxn],fa[maxn];
        int add(int x,int p)
        {
    //      printf("Add %d on %d
    ",x,p);
            int q;
            if (q=go[p][x])
            {
                if (l[p]+1==l[q]) return q;
                else
                {
                    int nq=++cnt;l[nq]=l[p]+1;
                    memcpy(go[nq],go[q],sizeof go[q]);
                    fa[nq]=fa[q];
                    fa[q]=nq;
                    for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
                    return nq;
                }
            }
            else
            {
                int np=++cnt; l[np]=l[p]+1;
                for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
                if (!p) fa[np]=1;
                else
                {
                    q=go[p][x];
                    if (l[q]==l[p]+1) fa[np]=q;
                    else
                    {
                        int nq=++cnt;
                        l[nq]=l[p]+1;
                        memcpy(go[nq],go[q],sizeof go[q]);
                        fa[nq]=fa[q];
                        fa[q]=fa[np]=nq;
                        for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
                    }
                }
                return np;
            }
        }
        void init()
        {cnt=1;memset(go,0,sizeof go);}
        void solve()
        {
            ll ans=0;
            F(i,1,cnt)
            {
    //          printf("%d --> %d
    ",i,fa[i]);
    //          printf("%d     %d
    ",l[i],l[fa[i]]);
                ans+=l[i]-l[fa[i]];
            }
            printf("%lld
    ",ans);
        }
    }sam;
       
    int h[maxn],to[maxn],ne[maxn],en=0,du[maxn];
       
    void addedge(int a,int b)
    {to[en]=b;ne[en]=h[a];h[a]=en++;du[a]++;}
       
    int n,c,a[maxn];
       
    void dfs(int o,int fa,int p)
    {
    //  printf("dfs on %d %d %d
    ",o,fa,p);
        int np=sam.add(a[o],p);
        for (int i=h[o];i>=0;i=ne[i]) if (to[i]!=fa) dfs(to[i],o,np);
    }
       
    int main()
    {
        sam.init();
        scanf("%d%d",&n,&c);
        memset(h,-1,sizeof h);
        F(i,1,n) scanf("%d",&a[i]);
        F(i,1,n-1)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            addedge(a,b);
            addedge(b,a);
        }
        F(i,1,n) if (du[i]==1) dfs(i,-1,1);
        sam.solve();
    }
    

      

  • 相关阅读:
    Prim+堆优化
    Tarjan缩点+建新图
    CF482A
    CF545C
    CF570B
    Python 入门2 list介绍
    Python 入门1 上传代码
    黑客与画家 第十三章
    黑客与画家 第十一章
    黑客与画家 第五章
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6486837.html
Copyright © 2020-2023  润新知