*在学习后缀自动机之前需要熟练掌握WA自动机、RE自动机与TLE自动机*
什么是后缀自动机
后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符串所有后缀的自动机。
它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到。
在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 可以用 SAM 轻松水过,由此 SAM 流行了起来。
一般来说,能用后缀自动机解决的问题都可以用后缀数组解决。但是后缀自动机也拥有自己的优点。
1812. Longest Common Substring II
题目大意:给出N(N <= 10)个长度不超过100000的字符串,求他们的最长公共连续子串。
时限:SPOJ上的2s
陈立杰的讲稿中用了 spoj 的1812作为例子,由于 spoj 太慢,所以只有O(n)的算法才能过掉本题,这时就要用到SAM了。
后缀自动机的构造
参考网上的各种模板即可。
后缀自动机的性质
裸的后缀自动机仅仅是一个可以接收子串的自动机,在它的状态结点上维护的性质才是解题的关键。
一个构造好的 SAM 实际上包含了两个图:由 go 数组组成的 DAG 图;由 par 指针构成的 parent 树。
SAM 的状态结点包含了很多重要的信息:
max:即代码中 val 变量,它表示该状态能够接受的最长的字符串长度。
min:表示该状态能够接受的最短的字符串长度。实际上等于该状态的 par 指针指向的结点的 val + 1。
max-min+1:表示该状态能够接受的不同的字符串数。
right:即 end-set 的个数,表示这个状态在字符串中出现了多少次,该状态能够表示的所有字符串均出现过 right 次。
par:par 指向了一个能够表示当前状态表示的所有字符串的最长公共后缀的结点。所有的状态的 par 指针构成了一个 parent 树,恰好是字符串的逆序的后缀树。
parent 树的拓扑序:序列中第i个状态的子结点必定在它之后,父结点必定在它之前。
后缀自动机的经典问题
uva 719 - Glass Beads 最小循环串
后缀自动机的遍历。
给一个字符串S,每次可以将它的第一个字符移到最后面,求这样能得到的字典序最小的字符串。
将字符串S拼接为SS,构造自动机,从根结点开始每次走最小编号的边,移动length(S)步就可以找到字典序最小的串。
由于 SAM 可以接受 SS 所有的子串,而字典序最小的字符串也必定是 SS 的子串,因此按照上面的规则移动就可以找到一个字典序最小的子串。
spoj 1811 Longest Common Substring 最长公共子串
给两个长度小于100000的字符串 A 和 B&