后缀自动机(SAM)
后缀自动机 (SAM)
1. 定义
字符串 \(s\) 的 SAM 是只接受 \(s\) 的后缀的最小 DFA,它包含了 \(s\) 所有子串的信息。
设 \(t_0\) 为起始状态,即空串对应的状态。SAM 是个 DAG。
2. endpos
设 \(s\) 的子串 \(t\) 的 \({\rm endpos}(t)\) 为 \(t\) 在 \(s\) 中终止位置的集合。
引理 1:若 \({\rm endpos}(u)={\rm endpos}(v)\land |u|<|v|\),则 \(u\) 是 \(v\) 的后缀。
引理 2:对于子串 \(u,v\) 且 \(|u|<|v|\),如果 \(u\) 是 \(v\) 的后缀,则 \({\rm endpos}(v)\subseteq {\rm endpos}(u)\);否则 \({\rm endpos}(u)\cap {\rm endpos}(v)=\varnothing\)。
定义一个等价类 \(a\),其包含的所有子串的 \({\rm endpos}(t)={\rm endpos}(a)\)。
这也就是说,一个等价类包含的所有子串在 \(s\) 内 “如影随形” 地同时出现。
定义 \({\rm long}(a)\) 为 \(a\) 中最长的子串,\({\rm len}(a)\) 为其长度;\({\rm short}(a)\) 为 \(a\) 中最短的子串,\({\rm minlen(a)}\) 为其长度。
引理 3:对于一个等价类 \(a\),其包含的所有子串的长度对应一个区间 \([{\rm minlen}(a),{\rm len}(a)]\) 内的所有整数。
那么对于一个等价类 \(a\),其包含的所有子串构成了以 \({\rm long}(a)\) 为下底,\({\rm short}(a)\) 为上底的 右侧直角梯形。长度较短的子串一定是长度较长的子串的后缀。
SAM 以等价类 \(a\) 作为节点,将子串的信息压缩到了极致。
3. link
定义 \({\rm link}(a)\) 为 \({\rm long}(a)\) 最长的不在 \(a\) 内的后缀对应的等价类。即 \(a\) 对应的 "直角梯形" 的上一层子串的等价类。
容易得到 \({\rm minlen}(a)-1={\rm len}({\rm link}(a))\)。
引理 4:将 \(a\) 向 \({\rm link}(a)\) 连边,得到一棵以 \(t_0\) 为根节点的根向树。
这棵树称为 后缀树,也称 parent 树。后缀树描述了等价类的分裂。
从任意一个结点 \(a\) 开始,向上遍历后缀树,遍历到的子串的长度构成一个区间 \([0,{\rm len}(a)]\)。
还可以得到:等价类 \(a\) 的 \({\rm endpos}\) 大小即为其在后缀树上所有儿子的 \({\rm endpos}\) 大小之和。
4. trans
定义 \({\rm trans}(a,c)\) 为在 \(a\) 之后加上一个字符 \(c\) 后到达的节点。
引理 5:若 \({\rm trans}(a,c)\) 存在,则其唯一。
推论:${\rm trans}(a,c) $ 描述了等价类的合并关系。
__引理 6:若 \(a\) 被多个节点的 \({\rm trans}\)指向,则这些节点对应着后缀树上的一条祖先后代链。 __
5. 增量构建法
在 \(s\) 后加上一个字符 \(c\),维护 SAM 的变化。
首先 \(s+c\) 一定在一个新等价类中,所以我们先新建一个节点 \(p\)。
设当前 \(s\) 所在的节点为 \(lst\),从 $lst $ 向上遍历后缀树。
找到第一个存在 \({\rm trans}(q,c)\) 的 \(q\)。设 \({\rm trans}(q,c)=z\)。
-
若不存在这样的 \(q\),则 \({\rm link}(p)=t_0\),结束;
-
若 \({\rm len}(q)+1={\rm len}(z)\),则令 \({\rm link}(p)=z\);
-
若 \({\rm len}(q)+1<{\rm len}(z)\),那么 \(z\) 上面的一部分的 \({\rm endpos}\) 多了 \(|s+c|\),而下面的部分没有。
于是 \(z\) 需要分裂为 \(up,dn\) 两个节点。令 \(dn=z\),新建一个 \(up\),将 \(dn\) 的所有信息赋值给 \(up\)。
令 \({\rm link}(p)=dn,{\rm link}(dn)=up\)。然后继续从 \(q\) 向上遍历后缀树,若 \({\rm trans}(q',c)=z\),那么修改其为 \(up\)。
SAM 的节点数量不多于 \(2n-1\),转移数不多于 \(3n-4\)。证明见 oi-wiki,不再赘述。
构建 SAM 的时间复杂度为 $O(n) $,空间复杂度为 \(O(n|\Sigma |)\)。若 \({\rm trans}\) 用平衡树实现,则时间复杂度为 \(O(n\log |\Sigma|)\),空间复杂度为 \(O(n)\)。

浙公网安备 33010602011771号