幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的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%的数据,除某两块空地与三个空地相邻外,其他空地都分别至多与两个空地相邻

题意:

设一个图中的每一条路径都是这个图的一个子串,求一个图中的本质不同的子串的个数。

题解:

先建图,然后根据题目给出的性质:

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

我们在每个入度为0的点开始搜索,建一个广义后缀自动机就行了

#include<bits/stdc++.h>
using namespace std;
const int N=2000010;
int n,q;
int tot,bian[N<<1],nxt[N<<1],head[N];
inline void add(int x,int y){
tot++,bian[tot]=y,nxt[tot]=head[x],head[x]=tot;
}
int s[N];
int a[N],c[N],rd[N];
struct SAM{
int lst[N],last,cnt,now;
long long size[N];
int ch[N][26],fa[N<<1],l[N<<1];
void ins(int c){
if(ch[last][c]&&l[ch[last][c]]==l[last]+1){
last=ch[last][c];
return;
}
int p=last,np=++cnt;last=np;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[p]+1==l[q])fa[np]=q;
else{
int nq=++cnt;l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof ch[q]);
fa[nq]=fa[q];fa[q]=fa[np]=nq;
for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
size[nq]=1;
}
}
size[np]=1;
}
void dfs(int x,int f){
last=lst[f];
now=x;
ins(s[x]);
lst[x]=last;
for(int i=head[x];i;i=nxt[i]){
int y=bian[i];
if(f==bian[i])continue;
dfs(y,x);
last=lst[x];
}
}
void build(){
lst[0]=1;cnt=1;
for(int i=1;i<=n;++i)if(rd[i]==1)dfs(i,0);
}
void calc(){
int ans=0;
for(int i=1;i<=cnt;++i)c[l[i]]++;
for(int i=1;i<=cnt;++i)c[i]+=c[i-1];
for(int i=1;i<=cnt;++i)a[c[l[i]]--]=i;
for(int i=cnt;i;--i){
int p=a[i];
for(int j=0;j<26;++j){
if(ch[p][j])size[p]+=size[ch[p][j]];
}
}
}
}sam;
int main(){
cin>>n>>q;
for(int i=1;i<=n;++i)scanf("%d",s+i);
for(int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);rd[x]++;
add(y,x);rd[y]++;
}
sam.build();
sam.calc();
cout<<sam.size[1]<<endl;
}

诸神眷顾的幻想乡(zjoi2015,bzoj3926)(广义后缀自动机)的更多相关文章

  1. [BZOJ]3926 诸神眷顾的幻想乡(ZJOI2015)

    听说大佬们都会后缀自动机. 小C看完SAM,想找个裸题练习一下模板.听说这题还是陈老师出的?(羊毛出在羊身上) Description  幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生 ...

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

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

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

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

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

    [BZOJ3926][Zjoi2015]诸神眷顾的幻想乡 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝 ...

  5. bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机)

    bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机) bzoj Luogu 题解时间 给你个无根trie树(你管这叫trie树?),问你选取一条 ...

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

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

  7. 【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 974  Solved: 573 Descriptio ...

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

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

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

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

随机推荐

  1. 安全运维 -- 更改ssh端口

    环境:Ubuntu 16 前言 黑客遍地都是,ssh/pop3/ftp等爆破工具的流行让站长的日常运维工作量大大加重.Metasplot,Bruter等工具更是针对以上协议有专门 的破解方法,有字典破 ...

  2. mysql 版本bug

    mysql命令gruop by报错this is incompatible with sql_mode=only_full_group_by 在mysql 工具 搜索或者插入数据时报下面错误: ERR ...

  3. 老板说你的UI设计的不高级?你肯定没用这7个技巧...

    对于每个网页设计师而言,在设计过程中总会碰到需要作出设计决策的时候.也许你的公司并没有全职设计师,而需求上则要求设计出全新的UI:又或者你正在制作一个你自己的个人项目,而你希望它比 Bootstrap ...

  4. 测试用例excel模板

    Index Precondition Action Test Data Expect Result Excute Date Pass/Fail

  5. OSGi karaf scheduler

    OSGi karaf scheduler karaf 中提供了定时任务管理,只需安装 feature:install scheduler 即可,然后在 karaf 容器中发布 org.apache.k ...

  6. vi 编辑器常用命令(转)

    常用vi编辑器命令行 对于VI的命令行,不需要特意的去记忆,写下来,让要用到的时候能找到就行 游标控制 h 游标向左移 j 游标向下移 k 游标向上移 l (or spacebar) 游标向右移 w ...

  7. jetty无法即时更新html、js、css等静态文件的解决办法

    网上搜了一大堆方法.最常见的是找到jetty\etc\webdefault.xml文件,找到useFileMappedBuffer参数,把true改为false <init-param> ...

  8. Ehcache配置参数简介

    < defaultCache         maxElementsInMemory = "10000"         maxElementsOnDisk = " ...

  9. 2018.09.23 atcoder Boxes and Candies(贪心)

    传送门 一道挺有意思的贪心. 从1到n依次满足条件. 注意要特判第一个数已经大于x的情况. 但是如何贪心吃呢? 如果靠左的数没有越界,我们吃靠右的数. 原因是下一次靠右的数就会成为靠左的数,相当于多贡 ...

  10. [GO]删除切片的某个值

    func removePro(ddbenv []*model.EnvInfo, k int) []*model.EnvInfo { :]...) } for k, v := range ddbenv ...