参考了hihocoder和clj的课件,看了看hzwer的代码,懂了些东西,记一下。
后缀自动机是一棵trie树。
给出一个字符串S,对于S的一个子串s,Right(s) 代表一个集合,为s在S中所有出现的结束位置集合。
以S=”aabbabd”为例,Right(“ab”) = {3, 6},因为”ab”一共出现了2次,结束位置分别是3和6。同理Right(“a”) = {1, 2, 5}, Right(“abba”) = {5}。对于一个字符串集合,若这个集合中所有的字符串拥有相同的Right集合,那么我们可以给这个集合一个状态s, 用Substring(s)代表这个集合,这个集合也对应着一个Right(s)集合。
那么现在就存在一个s <-> Substring <-> Right集合的一一对应关系。
对于Substring(s),存在longest(s)和shortest(s)分别代表Substring(s)中的最长和最短字符串,其长度分别为l(s)与r(s)。
对于一个longest(s),我们不断地去除他的第一个字符,直到其变为shortest(s),这个过程中出现的l(s)- r(s) + 1个字符串必然都属于Substring(s)。
若我们将shortest(s)的第一个字符删去(此时当然是假定shortest(s)不为空串),必然会导致状态的改变,因为此时的Right集合变大了,而s和Right(s),Substring(s)一一对应。
具体可以参照下图。
我们用fa(s)来代表从s进行的一次跳转到达的新状态。
若把状态按fa来建图,显然可以得到一个树形结构,我们称之为parent树。
对于这棵树存在以下性质:
1. max(fa(s))=min(s)−1 m a x ( f a ( s ) ) = m