zoukankan      html  css  js  c++  java
  • P3346 [ZJOI2015]诸神眷顾的幻想乡 广义SAM

    题意:

    戳这里

    分析:

    题目相当于让我们求树上有多少本质不同的路径,但是我们发现直接建 (trie) 树的话 (M) 字型的路径,没有办法表示出来

    然后我们发现题目有这么一句话 由于太阳花田的结构比较特殊,只与一个空地相邻的空地数量不超过 20 个

    ,这句话提醒了我们换个角度思考问题,我们查看题解可以发现,每一个 (M) 型的路径必定可以表示为以一个叶子结点为根的 (trie) 树上一条一条直的路径,所以直接以叶子为根建出广义 SAM,求出本质不同的子串

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
        int read()
        {
            int x=0,f=1;char ch=getchar();
            while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
            while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
            return x*f;
        }
    
        const int maxn = 2e6+5;
        int n,cnt;
        int c[maxn],head[maxn],deg[maxn];
    
        struct edge
        {
            int to,nxt;
        }e[maxn<<1];
    
        void add(int u,int v)
        {
            e[++cnt].to=v;
            e[cnt].nxt=head[u];
            head[u]=cnt;
            deg[v]++;
        }
    
        struct trie
        {
            int tot;
            int c[maxn],trans[maxn][15],link[maxn];
            trie(){tot=1;}
            int insert(int f,int x)
            {
                if(!trans[f][x]) trans[f][x]=++tot,link[tot]=f,c[tot]=x;
                return trans[f][x];
            }
        }tr;
    
        struct suffix_automaton
        {
            int tot;
            int trans[maxn][15],link[maxn],id[maxn],len[maxn];
            queue<int> q;
            suffix_automaton(){tot=1;}
    
            int insert(int x,int lst)
            {
                int cur=++tot,tmp=lst;
                len[cur]=len[tmp]+1;
                for(;tmp&&!trans[tmp][x];tmp=link[tmp]) trans[tmp][x]=cur;
                if(!tmp)
                {
                    link[cur]=1;
                }
                else
                {
                    int q=trans[tmp][x];
                    if(len[tmp]+1==len[q])
                    {
                        link[cur]=q;
                    }
                    else
                    {
                        int clone=++tot;
                        len[clone]=len[tmp]+1;
                        for(int i=0;i<=10;i++) trans[clone][i]=trans[q][i];
                        link[clone]=link[q];
                        link[cur]=link[q]=clone;
                        for(;tmp&&trans[tmp][x]==q;tmp=link[tmp]) trans[tmp][x]=clone;
                    }
                }
                return cur;
            }
        
            void build()
            {
                for(int i=0;i<=10;i++) if(tr.trans[1][i]) q.push(tr.trans[1][i]);
                id[1]=1;
                while(!q.empty())
                {
                    int u=q.front();q.pop();
                    id[u]=insert(tr.c[u],id[tr.link[u]]);
                    for(int i=0;i<=10;i++) if(tr.trans[u][i]) q.push(tr.trans[u][i]);
                }
            }
    
            void sort()
            {
                long long ans=0;
                for(int i=2;i<=tot;i++) ans+=len[i]-len[link[i]];
                printf("%lld
    ",ans);
            }
    
        }sam;
        
        void dfs(int u,int fa,int lst)
        {
            int tmp=tr.insert(lst,c[u]);
            for(int i=head[u];i;i=e[i].nxt)
            {
                int v=e[i].to;
                if(v==fa) continue;
                dfs(v,u,tmp);
            }
        }
    
        void work()
        {
            int a,b;
            n=read();a=read();
            for(int i=1;i<=n;i++) c[i]=read();
            for(int i=1;i<n;i++)
            {
                a=read();b=read();
                add(a,b);add(b,a);
            }
            for(int i=1;i<=n;i++) if(deg[i]==1) dfs(i,0,1);
            sam.build();
            sam.sort();
        }
    
    }
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    Collection<E>接口
    Iterable<T>接口
    Iterator<E>接口
    js图片压缩
    js计算最大公约数和最小公倍数
    canvas原生js写的贪吃蛇
    左右两栏div布局,高度自适应
    vue的图片路径,和背景图片路径打包后错误解决
    职责链模式
    js多个异步请求,按顺序执行next
  • 原文地址:https://www.cnblogs.com/youth518/p/14217114.html
Copyright © 2011-2022 走看看