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

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 843  Solved: 510
[Submit][Status][Discuss]

Description

幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日。

粉丝们非常热情,自发组织表演了一系列节目给幽香看。幽香当然也非常高兴啦。 
这时幽香发现了一件非常有趣的事情,太阳花田有n块空地。在过去,幽香为了方便,在这n块空地之间修建了n-1条边将它们连通起来。也就是说,这n块空地形成了一个树的结构。 
有n个粉丝们来到了太阳花田上。为了表达对幽香生日的祝贺,他们选择了c中颜色的衣服,每种颜色恰好可以用一个0到c-1之间的整数来表示。并且每个人都站在一个空地上,每个空地上也只有一个人。这样整个太阳花田就花花绿绿了。幽香看到了,感觉也非常开心。 
粉丝们策划的一个节目是这样的,选中两个粉丝A和B(A和B可以相同),然后A所在的空地到B所在的空地的路径上的粉丝依次跳起来(包括端
点),幽香就能看到一个长度为A到B之间路径上的所有粉丝的数目(包括A和B)的颜色序列。一开始大家打算让人一两个粉丝(注意:A,B和B,A是不同
的,他们形成的序列刚好相反,比如红绿蓝和蓝绿红)都来一次,但是有人指出这样可能会出现一些一模一样的颜色序列,会导致审美疲劳。 
于是他们想要问题,在这个树上,一共有多少可能的不同的颜色序列(子串)幽香可以看到呢? 
太阳花田的结构比较特殊,只与一个空地相邻的空地数量不超过20个。 

Input

第一行两个正整数n,c。表示空地数量和颜色数量。

第二行有n个0到c-1之间,由空格隔开的整数,依次表示第i块空地上的粉丝的衣服颜色。(这里我们按照节点标号从小到大的顺序依次给出每块空地上粉丝的衣服颜色)。 
接下来n-1行,每行两个正整数u,v,表示有一条连接空地u和空地v的边。 

Output

一行,输出一个整数,表示答案。

Sample Input

7 3
0 2 1 2 1 0 0
1 2
3 4
3 5
4 6
5 7
2 5

Sample Output

30

HINT

对于所有数据,1<=n<=100000, 1<=c<=10。

对于15%的数据,n<=2000。 
另有5%的数据,所有空地都至多与两个空地相邻。 
另有5%的数据,除一块空地与三个空地相邻外,其他空地都分别至多与两个空地相邻。 
另有5%的数据,除某两块空地与三个空地相邻外,其他空地都分别至多与两个空地相邻。
  
  知道要从每个叶子节点建trie树再合并,我就会做了。
 #include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=;
const int maxm=;
long long ans;
bool vis[maxm];
int n,sumc,cntE,c[maxn];
int fir[maxn],nxt[maxn<<],to[maxn<<];
void addedge(int a,int b){
nxt[++cntE]=fir[a];
fir[a]=cntE;
to[cntE]=b;
}
int st[maxm],topst;
int CH[maxm][],pos[maxm];
int fa[maxm],ch[maxm][],len[maxm];
struct SAM{
int cnt,last;
SAM(){
cnt=last=;
}
int Insert(int c){
int p=last,np=last=++cnt;len[np]=len[p]+;
while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
if(!p)fa[np]=;
else{
int q=ch[p][c];
if(len[p]+==len[q])
fa[np]=q;
else{
int nq=++cnt;len[nq]=len[p]+;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
while(ch[p][c]==q)ch[p][c]=nq,p=fa[p];
}
}
ans+=len[last]-len[fa[last]];
return last;
}
}sam;
struct Trie{
int cnt,rt;
Trie(){
rt=cnt=;
pos[rt]=;
}
void Insert(int &x,int p){
vis[p]=true;
if(!x)x=++cnt;
for(int i=fir[p];i;i=nxt[i])
if(!vis[to[i]])
Insert(CH[x][c[to[i]]],to[i]);
}
void Construct(int x){
for(int i=;i<sumc;i++)
if(CH[x][i]){
sam.last=pos[x];
pos[CH[x][i]]=sam.Insert(i);
}
for(int i=;i<sumc;i++)
if(CH[x][i])
Construct(CH[x][i]);
}
}trie;
int main(){
#ifndef ONLINE_JUDGE
freopen("zjoi15_substring.in","r",stdin);
freopen("zjoi15_substring.out","w",stdout);
#endif
scanf("%d%d",&n,&sumc);
for(int i=;i<=n;i++)
scanf("%d",&c[i]);
for(int i=,a,b;i<n;i++){
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}
for(int x=,tot=;x<=n;tot=,x++){
for(int i=fir[x];i;i=nxt[i])tot+=;
if(tot==)st[++topst]=x;
}
while(topst){
memset(vis,,sizeof(vis));
trie.Insert(CH[trie.rt][c[st[topst]]],st[topst]);
topst-=;
}
trie.Construct(trie.rt);
printf("%lld\n",ans);
return ;
}

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

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

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

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

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

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

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

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

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

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

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

  6. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡(后缀自动机)

    传送门 解题思路 因为叶节点不超过\(20\)个,所以可以枚举这些叶节点,并把这些节点当做根扫整棵树.可以证明所有的子串一定可以被便利到,然后可以对这些串建广义后缀自动机.\(dfs\)的时候要记录一 ...

  7. bzoj 3926 [Zjoi2015]诸神眷顾的幻想乡(SAM)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3926   [题意]   给定一棵树,每个节点都有相应的颜色,且保证叶子数不超过20,问 ...

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

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

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

    因为任何一条路径都可以看做某两个叶子节点之间路径的一部分,然后分别把20个叶节点当作根,把整棵树看作trie树,那么一条路径就能看作是从根到某个点这一条路的后缀,构建SAM就能维护不同子串的个数了. ...

随机推荐

  1. 布局重用 include merge ViewStub

    在布局优化中,Androi的官方提到了这三种布局<include />.<merge />.<ViewStub />,并介绍了这三种布局各有的优势,下面也是简单说一 ...

  2. 彻底删除mysql的方法(有隐藏文件)

    1.建议使用360进行卸载,可以彻底卸载软件 2.360会提醒删除注册表 3.这个隐藏文件要删除掉 在 C:\Documents and Settings\ 路径下搜索 MySQL 文件夹(默认隐藏的 ...

  3. PHP环境搭建所遇到的问题

    下午学校的机房搭建PHP组合包appserv开发环境的时候是没有任何问题的,但是到了自己的电脑上以后下砸的32位appserve一直无法正常由浏览器的localhos或者127.0.0.1 进入其ap ...

  4. Android App优化建议(转载)

    假如要Google Play上做一个最失败的案例,那最好的秘诀就是界面奇慢无比.耗电.耗内存.接下来就会得到用户的消极评论,最后名声也就臭了.即使你的应用设计精良.创意无限也没用. 耗电或者内存占用等 ...

  5. iOS开发之指定UIView的某几个角(小于4)为圆角

    在iOS开发中,我们经常会遇到View设置圆角的问题,如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可(项目需要使用QuartzCore ...

  6. C#入门经典(第五版)学习笔记(四)

    ---------------集合.比较和转换--------------- C#中的数组是作为System.Array类的实例实现的,它们是集合类(Collection Classes)中的一种类型 ...

  7. 24种设计模式--工厂方法模式【Factory Method Pattern】

    女娲补天的故事大家都听说过吧,今天不说这个,说女娲创造人的故事,可不是“造人”的工作,这个词被现代人滥用了. 这个故事是说,女娲在补了天后,下到凡间一看,哇塞,风景太优美了,天空是湛蓝的,水是清澈的, ...

  8. 利用正则表达式,给Json字段加引号

    { scheme: [ { query: [ [{ id: 'stdNumber', title: "标准号", compareType: 2 }], [{ id: 'CnName ...

  9. nodejs版本控制

    本方法基于https://segmentfault.com/a/1190000004855835修改 配置: 使用的nvmw的git 地址https://github.com/hakobera/nvm ...

  10. YII 框架使用之——创建应用

    linux环境为UBUNTU14.04,YII框架的版本是1.1.17 将下载的YII解压缩,压缩后会有三个文件夹,”demos,requirements,framework”,demos 当然就是演 ...