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

  小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做了一些小优化让自己舒服了一些。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define MS 10
#define MN 100005
#define MM 4000005
using namespace std;
struct edge{int nex,to;}e[MN<<1];
int mxl[MM],lnk[MM],son[MM][MS];
int sta[MN],col[MN],din;
int hr[MN],d[MN],pin;
int n,m;
ll ans;inline int read()
{int n=0,f=1; char c=getchar();while (c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}while (c>='0' && c<='9') {n=n*10+c-'0'; c=getchar();}return n*f;
}
inline void ins(int x,int y) {e[++pin]=(edge){hr[x],y}; hr[x]=pin;}int samins(int ncol,int lasta)
{int x=++din,lt;for (lt=lasta;lasta!=-1&&!son[lasta][ncol];lasta=lnk[lasta]) son[lasta][ncol]=x;if (lt==lasta) --din; else mxl[x]=mxl[lt]+1;if (lasta==-1) {lnk[x]=0; return x;}if (mxl[lasta]+1==mxl[son[lasta][ncol]])if (lt==lasta) return son[lasta][ncol];else {lnk[x]=son[lasta][ncol]; return x;}int y=++din,z=son[lasta][ncol];memcpy(son[y],son[z],sizeof(son[y]));lnk[y]=lnk[z]; mxl[y]=mxl[lasta]+1; lnk[z]=y;for (;son[lasta][ncol]==z;lasta=lnk[lasta]) son[lasta][ncol]=y;if (x!=y) lnk[x]=y;return x;
}void dfs(int x,int fat)
{sta[x]=samins(col[x],sta[fat]);for (register int i=hr[x];i;i=e[i].nex){if (e[i].to==fat) continue;dfs(e[i].to,x);}
}int main()
{register int i,x,y;n=read(); m=read(); lnk[0]=-1;for (i=1;i<=n;++i) col[i]=read();for (i=1;i<n;++i){x=read(); y=read();ins(x,y); ins(y,x);++d[x]; ++d[y];}for (i=1;i<=n;++i)if (d[i]==1) {memset(sta,0,sizeof(sta)); dfs(i,0);}for (i=1;i<=din;++i) ans+=(ll)mxl[i]-mxl[lnk[i]];printf("%lld",ans);
}

Last Word

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

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

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

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

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

转载于:https://www.cnblogs.com/ACMLCZH/p/7217797.html

[BZOJ]3926 诸神眷顾的幻想乡(ZJOI2015)相关推荐

  1. bzoj 3926 [Zjoi2015]诸神眷顾的幻想乡

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec   Memory Limit: 512 MB Submit: 1381   Solved: 811 [ Subm ...

  2. 【BZOJ 3926】【ZJOI 2015】 诸神眷顾的幻想乡

    [BZOJ 3926/ZJOI 2015] 诸神眷顾的幻想乡 [广义SA/广义SAM] 没想到陈立杰居然玩旧作- 题意: \;\;\;\;啊?~幻想乡?~一个树状太阳花田上每个点都有人穿着 c c种颜 ...

  3. bzoj 3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机)

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec   Memory Limit: 512 MB Submit: 1009   Solved: 596 [ Subm ...

  4. bzoj3926【ZJOI2015】诸神眷顾的幻想乡

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 790  Solved: 485 [Submit][ ...

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

    [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 1537  Solved: 892 Description 幽香 ...

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

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

  7. [ZJOI2015] 诸神眷顾的幻想乡

    P3256[ZJOI2015 Day1]诸神眷顾的幻想乡 时间限制 : 20000 MS   空间限制 : 524288 KB 问题描述 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生 ...

  8. 【刷题】BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

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

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

    这道题首先要读明白题,就是说叶子节点不超过20个,那么我们就可以以每一个叶子节点为根建一个广义后缀自动机,这样就一定能表示出来所有的子串,然后统计一下答案就可以啦. (广义后缀自动机就是把好多串放到一 ...

最新文章

  1. 如何更科学的进行SEO优化?保持排名稳定
  2. java用tkmapper分组查询_mybatis example group by count 分组求和 - java分组求和
  3. 岗位内推 | 微软亚洲互联网工程院自然语言处理组招聘算法研究实习生
  4. 微信适配国产操作系统:原生支持 Linux
  5. python连接sqlserver 多条sql语句后提交_利用python操作sqllite
  6. USB OTG简单介绍
  7. COMSOL电磁仿真案例——感应线圈
  8. Android 笔记 json GSON,Android中使用Gson解析JSON数据
  9. 计算机组装与维护试题精选,《计算机组装与维护》精选试题及答案
  10. 计算机用户报表清单,以下英文缩写和中文名字的对照中正确的是()。A.URL——用户报表清单B.CAD——计算机辅助设计C.USB——不...
  11. jqueryui引用出错(base is not a constructor,widget no found)
  12. histogram loss笔记
  13. android获取sdcard文件,android读取SDCard任意路径下的文件
  14. linux命令之journalctl —— 筑梦之路
  15. Single Image Haze Removal Using Dark Channel Prior 基于暗原色先验的单一图像去雾方法【翻译】
  16. paypal html5 支付,uniapp 对接 paypal支付 (h5,app端)
  17. 程序员,你需要些“脑力运动”了
  18. “胜兵先胜而后求战,败兵先战而后求胜”—系统分析师考试经验谈
  19. 实现火车站售票的例子
  20. 目标检测之YOLOv1到YOLOv3系列简介

热门文章

  1. 分布式系统监视zabbix讲解十之监控tomcat--技术流ken
  2. Tempter of the Bone
  3. 借伞,取经,停车,合作.
  4. 中国电信广东公司面试经验
  5. Draw Circle 沿着圆运动~
  6. db2 命令选项解释
  7. Debian下RPM包安装
  8. mpu6050 重力加速度_2021年高考物理一轮复习学与练 重力、弹力 、摩擦力 高中物理知识总结大全...
  9. devops实践指南_DevOps:掌握这些便捷指南
  10. 游戏计算获胜概率_伟大的命令行挑战赛的获胜者宣布