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

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

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 974  Solved: 573

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%的数据,除某两块空地与三个空地相邻外,其他空地都分别至多与两个空地相邻

【分析】

   

  这是我做的第二道广义SAM~

  广义SAM的字符管理的长度依然是 step[fa[x]]+1~step[x]哦。

  

  叶子节点小于等于20,考虑将每个叶子节点作为根把树给提起来形成一棵trie。(把跟到叶子的路径表示的串放到SAM上)
  dfs的时候记录一下它的父亲表示的点在SAM上的位置,把它记为last。
  最后统计答案是ans+=step[x]-step[fa[x]]。

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 #include<set>
  9 using namespace std;
 10 #define Maxn 100010
 11 #define LL long long
 12
 13 struct node
 14 {
 15     int step,pre,son[15];
 16 }t[40*Maxn];int tot=0;
 17 int last;
 18
 19 struct hp
 20 {
 21     int x,y,next;
 22 }a[2*Maxn];int al=0;
 23
 24 int col[Maxn],fa[Maxn],first[Maxn],rd[Maxn];
 25
 26 void ins(int x,int y)
 27 {
 28     a[++al].x=x;a[al].y=y;
 29     a[al].next=first[x];first[x]=al;
 30 }
 31
 32 void upd(int x)
 33 {
 34     memset(t[x].son,0,sizeof(t[x].son));
 35     t[x].pre=0;
 36 }
 37
 38 int extend(int k)
 39 {
 40     int np=++tot;upd(tot);
 41     t[np].step=t[last].step+1;
 42     int now=last;
 43     while(now&&!t[now].son[k])
 44     {
 45         t[now].son[k]=np;
 46         now=t[now].pre;
 47     }
 48     if(!now) t[np].pre=1;
 49     else
 50     {
 51         int p=now,q=t[now].son[k];
 52         if(t[p].step+1==t[q].step) t[np].pre=q;
 53         else
 54         {
 55             int nq=++tot;
 56             upd(tot);
 57             memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
 58             t[nq].pre=t[q].pre;
 59             t[q].pre=t[np].pre=nq;
 60             t[nq].step=t[p].step+1;
 61             while(now&&t[now].son[k]==q)
 62             {
 63                 t[now].son[k]=nq;
 64                 now=t[now].pre;
 65             }
 66         }
 67     }
 68     last=np;
 69     return np;
 70 }
 71
 72 void dfs(int x,int f)
 73 {
 74     int now=extend(col[x]);
 75     for(int i=first[x];i;i=a[i].next) if(a[i].y!=f)
 76     {
 77         last=now;
 78         dfs(a[i].y,x);
 79     }
 80 }
 81
 82 int n,c;
 83 void init()
 84 {
 85     scanf("%d%d",&n,&c);
 86     for(int i=1;i<=n;i++) {scanf("%d",&col[i]);col[i]++;}
 87     memset(first,0,sizeof(first));
 88     memset(rd,0,sizeof(rd));
 89     for(int i=1;i<n;i++)
 90     {
 91         int x,y;
 92         scanf("%d%d",&x,&y);
 93         rd[x]++;rd[y]++;
 94         ins(x,y);ins(y,x);
 95     }
 96     t[++tot].step=0;
 97     upd(tot);last=1;
 98     for(int i=1;i<=n;i++) if(rd[i]==1)
 99     {
100         dfs(i,0);
101         last=1;
102     }
103 }
104
105 int main()
106 {
107     init();
108     LL ans=0;
109     for(int i=1;i<=tot;i++) ans+=t[i].step-t[t[i].pre].step;
110     printf("%lld\n",ans);
111     return 0;
112 }

[BZOJ 3926]

2016-09-21 13:33:55

时间: 2024-08-15 16:35:29

【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)的相关文章

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

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

字符串(广义后缀自动机):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 [Zjoi20150]诸神眷顾的幻想乡(SAM)

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

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

题目大意:给定一棵树,每个节点有一个字符,求从一个节点出发沿最短路径走到另一个节点所构成的字符串一共有多少种 此生无悔入东方,来世愿生幻想乡 题目戳这里 注意一句话:太阳花田的结构比较特殊,只与一个空地相邻的空地的数量不超过20个 有奖问答:↑你看到这句话的第一反应是啥? 1.度数<=20 2.叶节点数<=20 仔细看几遍就能找到答案~ [捂脸熊]陈老师真是语文高手.... 叶节点数<=20还做啥了... 直接从每个叶节点DFS一遍,然后构建广义后缀自动机,最终答案就是每个节点的深度-p

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

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

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

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

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

[BZOJ3926][Zjoi2015]诸神眷顾的幻想乡 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建了n-1条边将它们连通起来.也就是说,这n块空地形成了一个树的结构. 有n个粉丝们来到了太阳花田上.为了表达对幽香生日的祝

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

被这道题坑了= =只与一个空地相连的空地不超过20个只与一个空地相连的空地不超过20个 因为很重要所以说两遍 就是说儿子节点最多只有20个 把这20个节点作为根遍历一遍所得到的tire所得到的所有不同子串就是答案了 怎么求? 这可是CLJ出的啊 想想她讲过什么 后缀自动机或可持久化后缀数组的经典应用 由于不会打可持久化后缀数组,就打了个自动机 自己对后缀自动机根本不熟,找时间在多做几道题 CODE: #include<cstdio> #include<iostream> #incl

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

传送门 一个广义后缀自动机模板. //Achen #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<queue> #include<cmath> const int N=4000007; typedef long long LL