听说大佬们都会后缀自动机。

  小C看完SAM,想找个裸题练习一下模板。听说这题还是陈老师出的?(羊毛出在羊身上)

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

Solution

  如果没学过后缀自动机可能会想到点分治(口胡),但是学了之后这就是一道裸题。

  这里先发一个SAM的教程:https://huntzhan.org/suffix-automaton-tutorial/,感觉完爆陈老师在WC上讲的好几条街。(个人观点,不喜勿喷)

  我们先从一条链入手,问题转化成一个字符串有多少本质不同的子串,我们可以用后缀自动机轻松解决。

  只要你理解后缀自动机的原理,我们就知道将后缀自动机上的每个点对应的字符串的个数全部加起来就是答案。

  同样,后缀自动机也适用于多个串。

  这道题还有顺序的因素,把字符串反过来再插入SAM即可。

  以上解决了树为一条链的情况。

  题目告诉我们这棵树的叶子节点最多只有20个,肯定就是O(20n)的做法啊。

  我们知道后缀自动机的插入操作实际上是在一个state后面再插入一个字符,我们只要记录下树上每个节点在本次遍历中对应的SAM中的state,插入一个节点就是在它父亲的state上插入即可。每次从一个叶子节点开始遍历整棵树,遍历一次就是构建了一棵树的SAM。

  新插入的后缀可能已经存在于SAM中,小C做了一些小优化让自己舒服了一些。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define ll long long
  5. #define MS 10
  6. #define MN 100005
  7. #define MM 4000005
  8. using namespace std;
  9. struct edge{int nex,to;}e[MN<<];
  10. int mxl[MM],lnk[MM],son[MM][MS];
  11. int sta[MN],col[MN],din;
  12. int hr[MN],d[MN],pin;
  13. int n,m;
  14. ll ans;
  15.  
  16. inline int read()
  17. {
  18. int n=,f=; char c=getchar();
  19. while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
  20. while (c>='' && c<='') {n=n*+c-''; c=getchar();}
  21. return n*f;
  22. }
  23. inline void ins(int x,int y) {e[++pin]=(edge){hr[x],y}; hr[x]=pin;}
  24.  
  25. int samins(int ncol,int lasta)
  26. {
  27. int x=++din,lt;
  28. for (lt=lasta;lasta!=-&&!son[lasta][ncol];lasta=lnk[lasta]) son[lasta][ncol]=x;
  29. if (lt==lasta) --din; else mxl[x]=mxl[lt]+;
  30. if (lasta==-) {lnk[x]=; return x;}
  31. if (mxl[lasta]+==mxl[son[lasta][ncol]])
  32. if (lt==lasta) return son[lasta][ncol];
  33. else {lnk[x]=son[lasta][ncol]; return x;}
  34. int y=++din,z=son[lasta][ncol];
  35. memcpy(son[y],son[z],sizeof(son[y]));
  36. lnk[y]=lnk[z]; mxl[y]=mxl[lasta]+; lnk[z]=y;
  37. for (;son[lasta][ncol]==z;lasta=lnk[lasta]) son[lasta][ncol]=y;
  38. if (x!=y) lnk[x]=y;
  39. return x;
  40. }
  41.  
  42. void dfs(int x,int fat)
  43. {
  44. sta[x]=samins(col[x],sta[fat]);
  45. for (register int i=hr[x];i;i=e[i].nex)
  46. {
  47. if (e[i].to==fat) continue;
  48. dfs(e[i].to,x);
  49. }
  50. }
  51.  
  52. int main()
  53. {
  54. register int i,x,y;
  55. n=read(); m=read(); lnk[]=-;
  56. for (i=;i<=n;++i) col[i]=read();
  57. for (i=;i<n;++i)
  58. {
  59. x=read(); y=read();
  60. ins(x,y); ins(y,x);
  61. ++d[x]; ++d[y];
  62. }
  63. for (i=;i<=n;++i)
  64. if (d[i]==) {memset(sta,,sizeof(sta)); dfs(i,);}
  65. for (i=;i<=din;++i) ans+=(ll)mxl[i]-mxl[lnk[i]];
  66. printf("%lld",ans);
  67. }

Last Word

  之前对着陈老师在WC上的讲稿使劲艹,发现根本理解不能。(神犇的画风实在可怕)

  然后随便在知乎上搜了搜,就看到一篇不错的教程,内容非常详尽,对关键点的分析也很到位。

  看来找到好的资源也是学习的关键啊。非常感谢这样的有心人。

  后缀自动机理解之后写起来意外地容易,本次默写给自己评个70分吧。

  当然陈老师的讲稿也不能完全否定,至少比网络上一些博客有用得多得多。(orz WJMZBMR)

[BZOJ]3926 诸神眷顾的幻想乡(ZJOI2015)的更多相关文章

  1. BZOJ 3926 诸神眷顾的幻想乡

    BZOJ 3926 诸神眷顾的幻想乡 开始看错题看成了每个点度数不超过20 后来翻了翻题解原来看错题的不止我一个 既然叶子数量不超过20,考虑树上的任何一条路径,以任何点为根时,如果它不是一条从上到下 ...

  2. bzoj 3926: 诸神眷顾的幻想乡 广义后缀自动机

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

  3. 诸神眷顾的幻想乡(zjoi2015,bzoj3926)(广义后缀自动机)

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

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

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

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

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

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

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

  7. BZOJ 3926 && ZJOI 2015 诸神眷顾的幻想乡 (广义后缀自动机)

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MB Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽 ...

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

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

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

    3926: [Zjoi20150]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 438  Solved: 273 Descripti ...

随机推荐

  1. 201421123042 《Java程序设计》第3周学习总结

    #Week03-面向对象入门 1. 本周学习总结 1.1写出你认为本周学习中比较重要的知识点关键词,如类.对象.封装等 本周学习关键词:类,对象,封装,关键词:final,this,statis. 1 ...

  2. 6块300G SCSI RAID5,两块硬盘损坏的数据恢复总结

    [用户单位]XXXX网站[数据恢复故障描述]DELL POWEREDGE 2850服务器,内置6块300G SCSI硬盘 ,组成RAID5,安装LINUX REDHAT 4操作系统,存储大量照片,文件 ...

  3. Linux "零拷贝" sendfile函数中文说明及实际操作

    Sendfile函数说明 #include ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); sendfile ...

  4. hibernate_exercise-many- to-one(1)

    多对一关系 1.创建t_user表.t_group表 2.在eclipse中创建对应的实体类 package com.eneity; public class User { private int i ...

  5. api-gateway实践(13)新服务网关 - 断路保护/熔断机制

    参考链接:SpringCloud的Hystrix(五) Hystrix机制 新需求列表 1.在线测试 根据定义,生成输入界面, 点击测试, 验证参数,发起调用,返回执行结果 2.熔断保护 两个实现类: ...

  6. GIT入门笔记(6)- 向版本库添加文本文件

    1.把文本文件添加到版本库? 所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外. 版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词&q ...

  7. ssh整合之六管理我们的配置文件

    1.我们的ssh搭建已经搭建好了,之前是纯xml方式,而且我们的配置文件,是一个框架一个配置文件.这样的话,配置文件中的内容就会很多,这样以后修改起来也会很麻烦,因        此,我们尝试着把这些 ...

  8. SQL Server 2012 管理新特性:AlwaysOn 可用性组

    SQL Server 2012 新特性(一)管理新特性:AlwaysOn 一.准备环境 1.准备4台计算机 域控制器DC1,IP地址192.168.1.1 主节点SQL1:IP地址192.168.1. ...

  9. python中导入模块的本质, 无法导入手写模块的解决办法

    最近身边一些朋友发生在项目当中编写自己模块,导入的时候无法导入的问题. 下面我来分享一下关于python中导入模块的一些基本知识. 1 导入模块时寻找路径 在每一个运行的python程序当中,都维护了 ...

  10. priority queue优先队列初次使用

    题目,排队打印问题 Input Format One line with a positive integer: the number of test cases (at most 20). Then ...