BZOJ 3926 Zjoi2015 诸神眷顾的幻想乡 后缀自动机

题目大意:给定一棵树,每个节点有一个字符,求从一个节点出发沿最短路径走到另一个节点所构成的字符串一共有多少种

此生无悔入东方,来世愿生幻想乡

题目戳这里

注意一句话:太阳花田的结构比较特殊,只与一个空地相邻的空地的数量不超过20个

有奖问答:↑你看到这句话的第一反应是啥?

1.度数<=20

2.叶节点数<=20

仔细看几遍就能找到答案~

[捂脸熊]陈老师真是语文高手。。。。

叶节点数<=20还做啥了。。。

直接从每个叶节点DFS一遍,然后构建广义后缀自动机,最终答案就是每个节点的深度-parent节点的深度之和

还有一种后缀数组的做法是DFS20遍构建一棵Trie树,然后将Trie树建成后缀数组(OTZ),然后一样搞就是了

OTZ

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
struct abcd{
    int to,next;
}table[M<<1];
int head[M],tot;
int n,c,a[M];
long long ans;
int degree[M];
void Add(int x,int y)
{
    table[++tot].to=y;
    table[tot].next=head[x];
    head[x]=tot;
}
namespace Suffix_Automaton{
    struct Sam{
        Sam *son[10],*parent;
        int max_dpt;
        bool v;
        void* operator new (size_t,int _)
        {
            #define L (1<<15)
            static Sam *mempool,*C;
            if(C==mempool)
                mempool=(C=new Sam[L])+L;
            C->max_dpt=_;
            C->parent=0x0;
            C->v=false;
            memset(C->son,0,sizeof C->son);
            return C++;
        }
    }*root=new (0)Sam;
    Sam* Extend(Sam *p,int x)
    {
        if(p->son[x]&&p->son[x]->max_dpt==p->max_dpt+1)
            return p->son[x];
        Sam *np=new (p->max_dpt+1)Sam;
        while(p&&!p->son[x])
            p->son[x]=np,p=p->parent;
        if(!p)
            np->parent=root;
        else
        {
            Sam *q=p->son[x];
            if(p->max_dpt+1==q->max_dpt)
                np->parent=q;
            else
            {
                Sam *nq=new (p->max_dpt+1)Sam;
                nq->parent=q->parent;
                memcpy(nq->son,q->son,sizeof nq->son);
                q->parent=nq;np->parent=nq;
                for(;p&&p->son[x]==q;p=p->parent)
                    p->son[x]=nq;
            }
        }
        return np;
    }
}
using namespace Suffix_Automaton;
Sam *node[M];
void DFS(int x,int from)
{
    int i;
    node[x]=Extend(node[from],a[x]);
    for(i=head[x];i;i=table[i].next)
        if(table[i].to!=from)
            DFS(table[i].to,x);
}
void BFS()
{
    static Sam *q[4004004];
    int i,r=0,h=0;
    q[++r]=root;
    while(r!=h)
    {
        Sam *p=q[++h];
        if(p!=root)
            ans+=p->max_dpt-p->parent->max_dpt;
        for(i=0;i<c;i++)
            if(p->son[i]&&!p->son[i]->v)
                p->son[i]->v=true,q[++r]=p->son[i];
    }
}
int main()
{
    int i,x,y;
    cin>>n>>c;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        Add(x,y);Add(y,x);
        degree[x]++;
        degree[y]++;
    }
    node[0]=root;
    for(i=1;i<=n;i++)
        if(degree[i]==1)
            DFS(i,0);
    BFS();
    cout<<ans<<endl;
    return 0;
}
时间: 2024-07-28 23:24:15

BZOJ 3926 Zjoi2015 诸神眷顾的幻想乡 后缀自动机的相关文章

字符串(广义后缀自动机):BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 843  Solved: 510[Submit][Status][Discuss] Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n

BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡

3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1017  Solved: 599[Submit][Status][Discuss] Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有

●BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3926题解&&代码: 后缀自动机,Trie树 如果以每个叶子为根,所有的子串一定在某一颗树的一条由祖先到子孙的链上. 由于叶子节点只有不超过20个,那么就可以从每个叶子开始dfs,把每个从根开始的串都加入一颗trie树. 显然,所有的子串都在trie树上,那么现在就需要统计trie树上有多少不同的子串. 对trie树建立后缀自动机,然后统计不同的子串个数即可. (本人不会在线建立tri

BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机 后缀自动机 字符串

https://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比较方便). 后缀自动机可以说是一种存子串的缩小点数的trie树,广义后缀自动机就是更改了一下塞点的方式让它可以塞多个子串. 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<

bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 后缀自动机在tire树上拓展

题意:有棵树每个点有个颜色(不超过10种),每个节点不超过20个儿子,问你每两点之间的颜色序列不同的有多少种 题解:先建出树,对于每个叶子节点,bfs一遍建在sam上,每次保留当前点在sam上的位置,拓展时用父亲节点在sam上的位置当成last即可.然后统计sam本质不同的字符串有多少个 注:dfs建树复杂度是错的,但是也能过这题 /************************************************************** Problem: 3926 User:

BZOJ3926 ZJOI2015 诸神眷顾的幻想乡 后缀自动机+DFS

题意:给定一颗字符树,求树中路径所构成的不同的字符串的数量,其中AB和BA视作不同的字符串 题解: 题目里有这样一句话:太阳花田的结构比较特殊,只与一个空地相邻的空地数量不超过20个. 一共有10W个点,却只有20个叶子……因此树上所有的字串就是以叶子为起点搜索出的所有字串,丽洁姐真的好善良啊- -(无雾) 这样从每个点开始就能跑出来一颗Trie树,对Trie构造广义后缀自动机——每个节点看成是一个根,在后面加字符的时候和普通的SAM一样. 然后在SAM上用DFS统计不同字串的数量即可 #inc

[BZOJ3926] [ZJOI2015]诸神眷顾的幻想乡|后缀自动机

唔..过去了一个多月才敢动一下一试的题呢..毕竟好神啊好神啊 看右边→就写着Orz yu990601 那不如就从他A掉的T3开始吧... 昨天晚上看了一下SAM..大概还是比较亲切的吧 毕竟去年暑假还是听过的...虽然并没有听懂 但是很开心的是现在再看CLJ的讲稿的时候大部分都能看懂了呢 直接这道题吧...首先这棵树的叶子节点不超过20个 然后一个很神奇的性质就是所有的子串都会在以某个叶子节点为根的树上以一条直线的姿态出现... 这么说不利于解题...也就是必定会作为叶子节点到以它为根的树上的某

BZOJ 3926: [Zjoi20150]诸神眷顾的幻想乡

3926: [Zjoi20150]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 438  Solved: 273 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修

bzoj 3926 [Zjoi20150]诸神眷顾的幻想乡(SAM)

3926: [Zjoi20150]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 615  Solved: 369[Submit][Status][Discuss] Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有