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;
    }
    
  • 相关阅读:
    1451. Rearrange Words in a Sentence
    1450. Number of Students Doing Homework at a Given Time
    1452. People Whose List of Favorite Companies Is Not a Subset of Another List
    1447. Simplified Fractions
    1446. Consecutive Characters
    1448. Count Good Nodes in Binary Tree
    709. To Lower Case
    211. Add and Search Word
    918. Maximum Sum Circular Subarray
    lua 时间戳和时间互转
  • 原文地址:https://www.cnblogs.com/youth518/p/14217114.html
Copyright © 2011-2022 走看看