【知识总结】后缀自动机的构建

参考资料:(APIO2018)从DFA到后缀自动机_张云帆

又一个学了很多遍都不会的算法/数据结构……(话说我怎么每篇知识总结一开始都是这句话qwq)

先orz后缀自动机之神兔崽子TzzDzz(顺便喂它最喜欢吃的叶子)

OrzTzzDzz

前排提示:由于作者很菜,且本文的目标是快速理解并写出 (背过) 后缀自动机的构建过程,所以将会省略很多结论的证明,语言也有不严谨之处,敬请谅解。如感兴趣可以参考文首提到的参考资料。阅读前建议先了解AC自动机。

(后缀自动机之神Tzz自己把后缀自动机玩得炉火纯青,给别人讲时却就让别人背代码。如果您不幸受到了Tzz的教育 (误导),请可以直接拉到最下方看代码然后把他嘴一顿)。

零、前言

很多字符串题要处理与子串有关的问题。如果想在AC自动机上处理一个字符串的所有子串,通常要将它的所有后缀插入(子串就是后缀的前缀),时空复杂度是 O ( n 2 ) O(n^2) O(n2)的。于是,我们需要充分利用插入的所有串都是同一个串的后缀这一性质来优化。后缀自动机,请。

(其实是Tzz太神仙了,自称不会KMP和AC自动机,见到所有字符串题都后缀自动机+哈希秒掉)

一、后缀自动机的相关定义和性质

以字符串"aabab"为例(下标从 0 0 0开始)。

一个字符串的 R i g h t Right Right集合:该字符串所有出现位置的右端点的集合。如字符串"ab"的 R i g h t Right Right集合是 { 2 , 4 } \{2,4\} {2,4},字符串"a"的 R i g h t Right Right集合是 { 0 , 1 , 3 } \{0,1,3\} {0,1,3}。定义空串的 R i g h t Right Right集合是 { i ∣ − 1 ≤ i &lt; n } \{i|-1\leq i &lt; n\} {i1i<n} − 1 -1 1表示在第一个字符之前的空串。两个 R i g h t Right Right集合之间要么交集为空,要么一个是另一个的子集(三分律)。稍后证明。

等价:如果两个字符串的 R i g h t Right Right集合相同,那么称它们“等价”。如字符串"ab"和"b"的 R i g h t Right Right集合都是 { 2 , 4 } \{2,4\} {2,4},所以它们是等价的。

和AC自动机相比,后缀自动机把所有等价字符串都缩成一个结点(即每个结点表示一个 R i g h t Right Right集合,点 u u u R i g h t Right Right集合记作 R u R_u Ru),是一个DAG(而不是像Trie树一样的树形结构)。稍后将证明,结点数不会超过 2 n + 1 2n+1 2n+1,转移数不会超过 3 n 3n 3n。即后缀自动机的空间是线性的。

一个结点的 f a fa fa:两个结点 u u u v v v,若 R v R_v Rv R u R_u Ru的真子集,且 u ′ u&#x27; u是所有这样的结点 u u u R i g h t Right Right集合的元素最少的,则 u ′ u&#x27; u v v v f a fa fa。根(空串)的 f a fa fa不存在。根据三分律,除了根外所有节点有且只有一个 f a fa fa,所以会组成一棵 f a fa fa树。

下面是对"aabab"建出的后缀自动机(鼠绘)(黑线是自动机的转移边,红线是 f a fa fa,绿字是该结点对应的子串)。可以看出,所有子串都对应一个结点,但一个结点可能对应多个子串(图中用逗号分隔)。

请在可以独立画出这幅图后再继续阅读。

SAM

结点的 m i n min min m a x max max:该结点对应的子串长度的最小/最大值。例如上图中 { 4 } \{4\} {4} m i n min min 3 3 3 m a x max max 4 4 4。可以证明,结点对应的子串长度一定是一个连续的区间 [ m i n , m a x ] [min,max] [min,max]。并且,如果 p p p q q q f a fa fa,那么有 m a x p max_p maxp= m i n q − 1 min_q-1 minq1。(两个结论都可以反证。)脑补一下可以发现, m a x max max m i n min min分别相当于从根节点到该结点的最长路和最短路的长度。不可能有两条路长度相等(想一想,为什么)。

下面来证明上面“稍后再证”的两个结论。

三分律:反证。设两不同状态为 p p p q q q,则三分律可表示为: R p ∩ R q = ∅ R_p\cap R_q=\emptyset RpRq= R p ⊂ R q R_p\subset R_q RpRq R p ⊃ R q R_p\supset R_q RpRq中有且只有一式成立。假设 R p ∩ R q ≠ ∅ R_p \cap R_q \neq \emptyset RpRq̸=,任取结束位置 r ∈ R p ∩ R q r\in R_p \cap R_q rRpRq。根据“一个子串只对应一个结点”, p p p q q q对应的子串没有交集,所以 [ m i n p , m a x p ] [min_p,max_p] [minp,maxp] [ m i n q , m a x q ] [min_q,max_q] [minq,maxq]没有交集。假设 m a x p &lt; m i n q max_p&lt;min_q maxp<minq,由因为它们具有相同的结束位置( r r r集合中的元素),则 p p p对应的串是 q q q对应的串的后缀。所以 R p ⊂ R q R_p \subset R_q RpRq。同理,当 m a x q &lt; m i n p max_q&lt;min_p maxq<minp,能推出 R p ⊃ R q R_p \supset R_q RpRq

结点数不超过 2 n + 1 2n+1 2n+1:设根结点 R i g h t Right Right集合大小为 i i i f a fa fa树的最大结点数为 f ( i ) f(i) f(i),则 f ( i ) = ∑ j = 1 k f ( x j ) + 1 ( ∑ j = 1 k x j ≤ i ) f(i)=\sum_{j=1}^k f(x_j)+1(\sum_{j=1}^k x_j\leq i) f(i)=j=1kf(xj)+1(j=1kxji)。由于 f ( x j ) f(x_j) f(xj)都是正的,所以就相当于 f ( i ) ≤ ∑ j = 1 k f ( x j ) + 1 ( ∑ j = 1 k x j = i ) f(i)\leq \sum_{j=1}^k f(x_j)+1(\sum_{j=1}^k x_j=i) f(i)j=1kf(xj)+1(j=1kxj=i)。当 i = 1 i=1 i=1显然满足 f ( i ) = 1 = 2 n − 1 f(i)=1=2n-1 f(i)=1=2n1,当 i = 1 i=1 i=1时脑补一下归纳,若对于任意 f ( j ) ( j &lt; i ) f(j)(j&lt;i) f(j)(j<i)都成立,则有 f ( i ) ≤ ∑ j = 1 k f ( x j ) ≤ 2 ∑ j = 1 k x j − k &lt; 2 i − 1 f(i)\leq \sum_{j=1}^k f(x_j)\leq 2\sum_{j=1}^k x_j-k&lt;2i-1 f(i)j=1kf(xj)2j=1kxjk<2i1。而根节点(空串) R i g h t Right Right集合结点数为 n + 1 n+1 n+1,所以结点数不超过 f ( n + 1 ) = 2 ( n + 1 ) − 1 = 2 n + 1 f(n+1)=2(n+1)-1=2n+1 f(n+1)=2(n+1)1=2n+1

转移数不超过 3 n 3n 3n:首先求一棵自动机的树形图,边数是点数减 1 1 1,即不超过 2 n 2n 2n。(证明待续……)

二、后缀自动机的构建

使用增量法。每次插入一个字符。

设正在插入第 n n n个字符 c c c n n n位置在当前后缀自动机中没有出现过,所以不会造成已有状态的合并,且一定会出现(至少)一个新结点,对应 R i g h t Right Right { n } \{n\} {n},对应的最长串长度( m a x max max)为 n n n

更进一步考虑新插入的结点会影响到原来的哪些结点。新字符只会与以 n − 1 n-1 n1结尾的子串形成新的子串,所以受影响的一定是 R i g h t Right Right集合包含 n − 1 n-1 n1的结点,即 R i g h t Right Right集合为 { n − 1 } \{n-1\} {n1}的结点(一定存在)在 f a fa fa树上到根的链。同时,如果这些结点本来就有 c c c字符的转移边,那么这些转移边指向的结点也会受影响(可能 R i g h t Right Right集合会增大)。下面无特殊说明的情况下,原串指前 n − 1 n-1 n1个字符组成的字符串, n p np np是新建的 R i g h t Right Right { n } \{n\} {n}的结点, p p p是一个 R i g h t Right Right集合包含 n − 1 n-1 n1的结点, q q q p p p c c c字符转移边指向的点(如果存在)。

如果 p p p没有 c c c字符的转移边,由于现在有了,直接向 n p np np连边即可。

如果一直到根都没有 c c c字符的转移边,说明 c c c字符在前 n − 1 n-1 n1个字符中没有出现过。把 n p np np f a fa fa置为根,插入结束。

如果 p p p可以通过 c c c字符转移到 q q q,且深度最大,那么进行如下讨论。

状态的“分裂”是指由于加入了新的字符导致原来等价的字符串不再等价。如"aabca"中"aab"、"ab"和"b"是等价的,在后面加入一个’b’后"ab"和"b"等价,但不与"aab"等价。脑补一下,分裂时分出的每个部分的长度都是连续的区间,字符串长度越短 R i g h t Right Right集合越大。

前面提到过, m a x p max_p maxp就是根到 p p p的最长路,所以 m a x q ≥ m a x p + 1 max_q\geq max_p+1 maxqmaxp+1

如果 m a x p + 1 = m a x q max_p+1=max_q maxp+1=maxq,说明原来 p p p中对应的最长串后面加一个字符 c c c形成了 q q q对应的最长串。所以,所有 p p p最长串的后缀加上一个字符 c c c都是 q q q最长串的后缀。 q q q对应的子串集合是这些后缀的子集。因此 q q q不会分裂,只是 R i g h t Right Right集合中增加了一个 n n n

如果 m a x p + 1 &lt; m a x q max_p+1&lt;max_q maxp+1<maxq,说明在 q q q的最长串不是由 p p p途径转移而来的,所以 q q q的最长串去掉最后一个字符 c c c不是原串的后缀。加入一个字符 c c c后,只有从 p p p转移到 q q q的子串的出现位置会增加,而比 m a x p + 1 max_p+1 maxp+1还长的那部分不会变。所以此时 q q q分裂为两个结点。称 R i g h t Right Right集合更新(即包含 { n } \{n\} {n}的结点)为 n q nq nq

脑补一下, n q nq nq R i g h t Right Right集合是原来 q q q R i g h t Right Right加上 n n n,所以它应当成为 q q q f a fa fa。而 n q nq nq f a fa fa应当是 q q q原本的 f a fa fa。因为 n q nq nq中所有串都是 p p p加上一个字符 c c c得到的,所以 m a x n q = m a x p + 1 max_{nq}=max_p+1 maxnq=maxp+1。同时, p p p到根的路径上所有能转移到 q q q的结点都应该改为转移到 n q nq nq(转移到 q q q f a fa fa树上的祖先的点不理。这样修改的点一定是链上连续的一段)。

这个构造方式的时间复杂度均摊是 O ( n ) O(n) O(n)的(然而并不会证明

完结撒花。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值