博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机)
阅读量:5130 次
发布时间:2019-06-13

本文共 2601 字,大约阅读时间需要 8 分钟。

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

解题思路:

可能是题目描述最吓人的题了。

这道题最重要的问题就是如何将所有字符串遍历一遍。

考虑正常走会有什么问题,那就是可能有字符串被起点分开了。

那么只需要在末端开始遍历就可以处理了。

树的末端就是叶节点。

20个还不多,遍历20次。

最后在后缀自动机上统计答案。

代码:

1 #include
2 #include
3 typedef long long lnt; 4 struct pnt{ 5 int hd; 6 int val; 7 int ind; 8 }p[3000000]; 9 struct sant{10 int tranc[10];11 int pre;12 int len;13 }s[3000000];14 struct ent{15 int twd;16 int lst;17 }e[3000000];18 int siz;19 int cnt;20 int n,c;21 void ade(int f,int t)22 {23 cnt++;24 e[cnt].twd=t;25 e[cnt].lst=p[f].hd;26 p[f].hd=cnt;27 p[t].ind++;28 return ;29 }30 int Insert(int c,int fin)31 {32 int nwp,lsp,nwq,lsq;33 nwp=++siz;34 s[nwp].len=s[fin].len+1;35 for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)36 s[lsp].tranc[c]=nwp;37 if(!lsp)38 s[nwp].pre=1;39 else{40 lsq=s[lsp].tranc[c];41 if(s[lsq].len==s[lsp].len+1)42 s[nwp].pre=lsq;43 else{44 nwq=++siz;45 s[nwq]=s[lsq];46 s[nwq].len=s[lsp].len+1;47 s[lsq].pre=s[nwp].pre=nwq;48 while(s[lsp].tranc[c]==lsq)49 {50 s[lsp].tranc[c]=nwq;51 lsp=s[lsp].pre;52 }53 }54 }55 return nwp;56 }57 void Sam_dfs(int x,int f,int fin)58 {59 fin=Insert(p[x].val,fin);60 for(int i=p[x].hd;i;i=e[i].lst)61 {62 int to=e[i].twd;63 if(to==f)64 continue;65 Sam_dfs(to,x,fin);66 }67 return ;68 }69 int main()70 {71 //freopen("a.in","r",stdin);72 siz++;73 scanf("%d%d",&n,&c);74 for(int i=1;i<=n;i++)75 scanf("%d",&p[i].val);76 for(int i=1;i

 

转载于:https://www.cnblogs.com/blog-Dr-J/p/10084685.html

你可能感兴趣的文章
Entity Framework的一个坑
查看>>
jsDoc 使用及配置!
查看>>
C++11 正则表达式简单运用
查看>>
Yum本地源配置
查看>>
从整库逻辑备份单独抽出一张表
查看>>
[转载]DbHelper的常用数据库类
查看>>
C#正则表达式占位符
查看>>
weblogic sockets 和 thread 问题解决
查看>>
《那些年啊,那些事——一个程序员的奋斗史》——47
查看>>
php curl 登陆百度贴吧(经历记录)
查看>>
【新鲜出炉】影响设计美观的2012年度终极收藏的最佳字体集合
查看>>
MySQL_产品昨日库存与历史入库历史出库成本_20161124
查看>>
[Training Video - 4] [Groovy] Object equality and variable equality check
查看>>
ReactiveCocoa的使用方法
查看>>
JS获取页面复选框选中的值
查看>>
lucene 7.x 排序
查看>>
python_控制台输出带颜色的文字方法
查看>>
asyncpipe
查看>>
Python模块——unittest 单元测试
查看>>
hdu 1864(01背包,输入处理真烦)
查看>>