【题目链接】

  http://www.lydsy.com/JudgeOnline/problem.php?id=3926

 
【题意】
 
  给定一棵树,每个节点都有相应的颜色,且保证叶子数不超过20,问有多少条本质不同的颜色路径。
 
【思路】
 
  从每个叶子开始dfs,构建广义后缀自动机,答案为l[i]-l[fa[i]]的和。
  从每个叶子dfs,将每个叶子到所有节点的路径作为一个字符串插入SAM,这样就覆盖了所有的树上路径,树上的一条路径一定对应着一个字符串的某个子串。
  SAM本身会忽略重复的子串,一个结点所代表的字符串的个数是l[i]-l[fa[i]],因此sigma{ l[i]-l[fa[i]] }即为加入的所有字符串中本质不同的子串数目。
 
【科普】
 
  关于广义后缀自动机:

  传统后缀自动机是解决单个主串的匹配问题,广义后缀自动机可以用来解决多个主串的匹配问题。

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

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

                                        Quote from here

 
【代码】
 
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std; const int N = 4*1e6+10; vector<int> g[N];
int n,m,c[N],in[N]; int sz,fa[N],ch[N][10],l[N];
int add(int c,int p) {
int np=++sz; l[np]=l[p]+1;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=1;
else {
int q=ch[p][c];
if(l[q]==l[p]+1) fa[np]=q;
else {
int nq=++sz; l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
for(;q==ch[p][c];p=fa[p]) ch[p][c]=nq;
}
}
return np;
}
void dfs(int u,int fa,int p) {
int t=add(c[u],p);
for(int i=0;i<g[u].size();i++) {
int v=g[u][i];
if(v!=fa) dfs(v,u,t);
}
} void read(int& x) {
char c=getchar(); int f=1; x=0;
while(!isdigit(c)) {if(c=='-')f=-1; c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=f;
}
int main() {
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
read(n),read(m);
for(int i=1;i<=n;i++) read(c[i]);
int u,v;
for(int i=0;i<n-1;i++) {
read(u),read(v);
g[u].push_back(v);
g[v].push_back(u);
in[v]++,in[u]++;
}
sz=1;
for(int i=1;i<=n;i++)
if(in[i]==1) dfs(i,-1,1);
long long ans=0;
for(int i=1;i<=sz;i++)
ans+=l[i]-l[fa[i]];
printf("%lld",ans);
return 0;
}

  

 

bzoj 3926 [Zjoi2015]诸神眷顾的幻想乡(SAM)的更多相关文章

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

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1017  Solved: 599[Submit][S ...

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

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 843  Solved: 510[Submit][St ...

  3. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 [广义后缀自动机 Trie]

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1124  Solved: 660[Submit][S ...

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

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3926题解&&代码: 后缀自动机,Trie树 如果以每个叶子为根,所有的子串一 ...

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

    https://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比 ...

  6. 【刷题】BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

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

  7. BZOJ.3926.[ZJOI2015]诸神眷顾的幻想乡(广义后缀自动机)

    题目链接 要对多个串同时建立SAM,有两种方法: 1.将所有串拼起来,中间用分隔符隔开,插入字符正常插入即可. 2.在这些串的Trie上建SAM.实际上并不需要建Trie,还是只需要正常插入(因为本来 ...

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

    神奇的性质,叶子节点不超过20个. 然后把这些节点提出来构成一颗新树,那么这些树恰好包含了所有的情况. 所以直接广义后缀自动机. 然后统计本质不同的字符串就很简单显然了. #include <c ...

  9. bzoj 3926: [Zjoi2015]诸神眷顾的幻想乡【SAM】

    有一个显然的性质就是每个串一定在某个叶子为根的树中是一条直的链 然后因为SAM里是不会有相同状态的,所以以每个叶子为根dfs一遍,并且动态构造SAM(这里的节点u的last指向父亲),最后统计答案就是 ...

随机推荐

  1. JavaScript原生错误及检测

    JavaScript代码在运行时可能产生的错误共有六种类型: 语法错误 类型错误 范围错误 eval错误 引用错误 URI错误 使用try-catch语句检测错误类型 try{ }catch(erro ...

  2. 客户端动态调用cxf websevice 异常

    三月 30, 2014 10:06:40 上午 org.apache.cxf.common.jaxb.JAXBUtils logGeneratedClassNames 信息: Created clas ...

  3. 一个C语言宏展开问题

    转自一个C语言宏展开问题 一个令人比较迷惑的问题,学C语言好多年,今天终于搞明白,记之. ------------------------------------------------------- ...

  4. iOS 并发:NSOperation 与调度队列入门(1)

    一直以来,并发都被视为 iOS 开发中的「洪水猛兽」.许多开发者都将其视为危险地带,唯恐避之而不及.更有谣传认为,多线程代码应该尽力避免.笔者同意,如果你对并发的了解不够深入,就容易造成危险.但是,危 ...

  5. tomcat 端口被占用

    找到占用8080端口的是PID为 2392的进程,于是 ctrl +shift+esc ,然后将这个进程结束掉.

  6. HDU1632+半平面交

    模板题 题意:给定两个凸多边形,求出合并后的面积,这个合并后的面积不包括重叠部分. #include<stdio.h> #include<string.h> #include& ...

  7. UVALive - 4287 Proving Equivalences

    给定n个命题之间的已经证明的关系如 a b表示已经证明蕴含式a→b,要求还需要再作多少次证明使得所有的命题都是等价的.将每个命题看成一个点,已经证明的命题之间连一条边,问题转化为添加多少条单向边使得图 ...

  8. Ubuntu下APACHE HTTPS安装和配置

    http://blog.csdn.net/newjueqi/article/details/9789659

  9. datetime 和 smalldatetime

    用于表示某天的日期和时间的数据类型. datetime 和 smalldatetime 表示某天的日期和时间. 数据类型 范围 精确度 datetime 1753 年 1 月 1 日到 9999 年 ...

  10. 【HDOJ】1045 Fire Net

    经典深搜.注意满足条件. #include <stdio.h> #include <string.h> #define MAXNUM 5 char map[MAXNUM][MA ...