http://www.lydsy.com/JudgeOnline/problem.php?id=3926 (题目链接)

题意

  给出一棵树,每个节点有一个编号,范围在${[0,9]}$。一个序列是指树上某条路径上的点的编号按顺序依次相接连成的字符串。问有多少个不同的序列。

Solution

  广义后缀自动机,看起来好高深的样子,然而题解却很简单。这道题好像只是一个很简单的应用吧。

  首先题目数据范围有一个很特殊的地方:叶子节点数${<=20}$。嘿嘿嘿,这就可以搞事情了。

  我们往叶子节点上想,慢慢就会发现一个结论:任意一个存在的序列都可以以某个叶子节点为根进行dfs得到。

  所以,我们对于每个叶子节点建立一个${trie}$树,将这些${trie}$树构成一个广义后缀自动机,最后在后缀自动机中扫一遍每一个状态,它所贡献的不同序列个数就是它的${len}$减父亲的${len}$。

  下面引用一段广义后缀自动机的介绍,来自:http://blog.csdn.net/wangzhen_yu/article/details/45481269

广义后缀自动机:

  传统后缀自动机是解决单个主串的匹配问题,广义后缀自动机可以用来解决多个主串的匹配问题,这样我们就不用把所有主串接在一起构造自动机了,大大节省了时间空间。

  如何将多个主串构建成广义后缀自动机?先将一个主串建立成后缀自动机,然后将重置last,令last=root,下一个字符串再从头节点开始建立,下一状态如果不存在,则以后缀自动机的规则进行建立新节点。

  如果下一状态已经建立,我们直接转移到该状态即可,既然到达该状态,说明已经匹配成功的字符串的所有后缀都在该状态及该状态的父节点,父节点的父节点...直到root,所以我们需要对该状态以及他的父节点,他的父节点的父节点。。。直到root进行内容更新,更新的内容当然因题目而异,如果求某个字符串出现的个数,就cnt++,如果求某个字符串出现的位置,就将位置存在结点的一个数组里。

细节

  因为是广义后缀自动机,注意数组大小。答案开LL。

代码

// bzoj3926
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#define RG register
#define LL long long
#define inf (1ll<<30)
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=2000010;
int ch[maxn<<1][10],par[maxn<<1],len[maxn<<1],Dargen,sz;
int head[maxn],deg[maxn],a[maxn],n,C,cnt; struct edge {int to,next;}e[maxn<<1]; void link(int u,int v) {
e[++cnt]=(edge){v,head[u]};head[u]=cnt;
e[++cnt]=(edge){u,head[v]};head[v]=cnt;
}
int Extend(int c,int p) {
int np=++sz;
len[np]=len[p]+1;
for (;p && !ch[p][c];p=par[p]) ch[p][c]=np;
if (!p) par[np]=Dargen;
else {
int q=ch[p][c];
if (len[q]==len[p]+1) par[np]=q;
else {
int nq=++sz;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
par[nq]=par[q];
par[np]=par[q]=nq;
for (;p && ch[p][c]==q;p=par[p]) ch[p][c]=nq;
}
}
return np;
}
void dfs(int x,int fa,int p) {
int t=Extend(a[x],p);
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) dfs(e[i].to,x,t);
}
int main() {
scanf("%d%d",&n,&C);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int u,v,i=1;i<n;i++) {
scanf("%d%d",&u,&v);
link(u,v);deg[u]++;deg[v]++;
}
Dargen=sz=1;
for (int i=1;i<=n;i++) if (deg[i]==1) dfs(i,0,1);
LL ans=0;
for (int i=1;i<=sz;i++) ans+=len[i]-len[par[i]];
printf("%lld",ans);
return 0;
}

【bzoj3926】 Zjoi2015—诸神眷顾的幻想乡的更多相关文章

  1. bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 对[广义后缀自动机]的一些理解

    先说一下对后缀自动机的理解,主要是对构造过程的理解. 构造中,我们已经得到了前L个字符的后缀自动机,现在我们要得到L+1个字符的后缀自动机,什么需要改变呢? 首先,子串$[0,L+1)$对应的状态不存 ...

  2. BZOJ3926 [Zjoi2015]诸神眷顾的幻想乡 字符串 SAM

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3926.html 题目传送门 - BZOJ3926 题意 给定一个有 $n$ 个节点,最多只有 $20$ ...

  3. BZOJ3926:[ZJOI2015]诸神眷顾的幻想乡(广义SAM)

    Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看. ...

  4. [BZOJ3926][ZJOI2015]诸神眷顾的幻想乡(后缀自动机)

    日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦.  这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去 ...

  5. BZOJ3926 Zjoi2015 诸神眷顾的幻想乡【广义后缀自动机】

    Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看. ...

  6. BZOJ3926 [Zjoi2015]诸神眷顾的幻想乡 【广义后缀自动机】

    题目 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴 ...

  7. BZOJ3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机)

    Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看. ...

  8. BZOJ3926 ZJOI2015诸神眷顾的幻想乡(广义后缀自动机)

    对多串建立SAM的一种方法是建trie再对trie建SAM.构造方式分为在线(也即不建trie而是依次插入每个串,或在trie上dfs)和离线(也即建好trie再bfs).其中离线构造与单串的构造方式 ...

  9. bzoj3926: [Zjoi2015]诸神眷顾的幻想乡

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  10. BZOJ3926 ZJOI2015 诸神眷顾的幻想乡 Trie、广义SAM

    传送门 树上的任意一条路径一定会在以某一个叶子节点为根的树上成为一条直上直下的链,而总共只有\(20\)个叶子节点. 于是每一次选所有叶子节点中的一个作为根,形成一个\(Trie\),把\(20\)个 ...

随机推荐

  1. 3. 第一个程序Hello, World!

    第一个接口 HelloWorld 本项目所有代码均可在github上下载. 1. 编辑config.py # 基础配置类 import os class Config(object): ROOT = ...

  2. Windows下LimeSDR Mini使用说明

    本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 LimeSDR链接:https://item.taobao.com/item.htm?spm=a230r.1 ...

  3. ubuntu HackRF One相关环境搭建

    本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 HackRF链接:https://item.taobao.com/item.htm?spm=a1z10.1- ...

  4. Spring AOP部分源码分析

    Spring源码流程分析-AOP相关 根据Spring源码整理,其中Calculator为自定义的实现方法. AnnotationConfigApplicationContext()加载配置类的流程 ...

  5. cmd下执行mysql

    1.  mysql -uroot -p1234; 2.  show databases; 3.  use testnode; 4. 创建数据库表 CREATE DATABASE `node` DEFA ...

  6. Linux命令之mount挂载

    挂载概念 Linux中的根目录以外的文件要想被访问,需要将其“关联”到根目录下的某个目录来实现,这种关联操作就是“挂载”,这个目录就是“挂载点”,解除次关联关系的过程称之为“卸载”. 注意:“挂载点” ...

  7. css修改input自动提示的黄色背景

    css修改input自动提示的黄色背景 input:-webkit-autofill { background-color: #FAFFBD; background-image: none; -web ...

  8. BUAAMOOC-Alpha版本发布说明

    BUAAMOOC-Alpha版本发布说明 本说明为BUAAMOOCv1.0版发布说明. 软件截图 上届软件截图 可以看到上届的界面做的很简陋,对于登录.查看课程列表.观看视频等操作需要跳转多个页面,视 ...

  9. crontab任务不生效

    新建php脚本ctTest.php,代码如下: <?php /****************************************************************** ...

  10. 《Spring2之站立会议9》

    <Spring2之站立会议9> 昨天,添加了注册界面: 今天,添加了表情库: 遇到的问题:由于资源有限,感觉设计的不完美并且途中也遇到了好多问题.