[补档计划] SAM

  对于一个算法或者数据结构的学习, 我们首先要弄清它的概念, 然后理解它的构建, 进而是实现和复杂度分析, 最后考虑如何应用它.

  现在学习的是 SAM, Suffix Automaton, 后缀自动机.

  推荐陈立杰的冬令营讲稿. https://wenku.baidu.com/view/90f22eec551810a6f4248606.html

什么是自动机?

  有限状态自动机的功能是识别字符串. 令一个自动机 $A$ , 若 $A$ 能识别字符串 $S$ , 则 $A(S) = True$ ; 若不能识别字符串 $S$ , 则 $A(S) = False$ . 特别地, 后缀自动机能识别一个字符串的所有后缀. 例如, 令 $S = ababb$ , 对 $S$ 构建后缀自动机 $A$ , 则 $A(bb) = True$, $A(abb) = True$, $A(baa) = False$.

  如何用一些量刻画一个自动机? 我们需要用一个五元组: 字符集, 状态集, 初始状态, 结束状态, 转移函数.

  自动机 $A$ 能识别的字符串 $S$ , 要满足 $trans(A, S)\in 结束状态$ , 记作 $Reg(A)$ . 从自动机 $A$ 的某个状态 $s$ 作为起始节点, 能识别的字符串 $S$ , 要满足 $trans(s, S)\in 结束状态$ , 记作 $Reg(s)$ .

后缀自动机的定义

  对于字符串 $S$ , 对应后缀自动机 SAM .

  SAM 是能识别字符串 $S$ 的所有后缀的自动机. 即 $SAM(s) = True$, 当且仅当 $s$ 是 $S$ 的后缀.

  同时在后面我们能看出, SAM 能识别字符串 $S$ 的所有子串.

最简单的实现

  将每个后缀插入 Trie树 中. 状态集为 Trie树 的 $V$ , 起始状态为 Trie树 的 Root, 结束状态为 Trie树 的叶子节点, 转移函数为 Trie树 的边.

  时间复杂度和空间复杂度均为 $O(n^2)$ . 这可能很不能接受.

  考虑进行优化, 减少 SAM 的状态数.

最简状态后缀自动机

  顾名思义, 就是状态数最少的 SAM, 后面我们可以证明状态数为 $O(n)$ .

  我们需要先研究它的性质, 对它充分理解并应用, 基于此才能构建出 最简状态SAM .

  为了研究的方便, 我们设定记号 $ST(str) = trans(init, str)$ , 即从开始状态开始读入字符串 str 之后, 能到达的状态.

  令母串为 $S$ , 它的后缀集合为 $Suf$ , 连续子串集合为 $Fac$ .

  从位置 $a$ 开始的后缀为 $Suffix(a)$.

  $S[l,r)$ 表示 $S[l : r-1]$, 下标从 $0$ 开始.

  对于一个字符串 $s$, 若 $s\in Fac$ , 则 $ST(s)\ne null$ . 因为不能放过可能识别到后缀的可能性.

  对于一个字符串 $s$, 若 $s\not\in Fac$ , 则 $ST(s) = null$ . 因为既然不是子串, 那么也不可能识别到后缀, 我们要最简状态数.

  

  对于 $ST(s)$ , 假设 $x\in Reg(ST(s))$ , 则 $sx\in Reg(A)$ , 所以 $sx$ 为 $S$ 的后缀, 所以 $x$ 为 $S$ 的后缀.

  所以对于一个状态 $a$ , $Reg(a)$ 为 $S$ 的某些后缀的集合.

  更具体地, 如果 $s$ 在 $[l,r)$ 出现过, 那么 $Suffix(r)\in Reg(ST(s))$ .

  记 $Right(s) = \left\{ r_1,r_2,...,r_n \right\}$ , 则 $Reg(ST(s))$ 由 $Right(s)$ 决定.

  

时间: 2024-10-06 04:22:56

[补档计划] SAM的相关文章

[补档计划] 字符串 之 知识点汇总

学习一个算法, 需要弄清一些地方 ① 问题与算法的概念 ② 算法以及其思维轨迹 ③ 实现以及其思维轨迹 ④ 复杂度分析 ⑤ 应用 KMP算法 字符串匹配与KMP算法 为了方便弄清问题, 应该从特例入手. 设 A = " ababababb " , B = " ababa " , 我们要研究下面三个递进层次的字符串匹配问题: ① 是否存在 A 的子串等于 B ② 有几个 A 的子串等于 B ③ A 的哪些位置的子串等于 B KMP算法可以直接在线性复杂度解决问题③,

[补档计划] 类欧几里得算法

$$\begin{aligned} f(a, b, c, n) & = \sum_{i = 0}^n \lfloor \frac{ai + b}{c} \rfloor \\ & = \sum_{i = 0}^n \sum_{j = 0}^{m-1} [j < \lfloor \frac{ai + b}{c} \rfloor] \\ & = \sum_{i = 0}^n \sum_{j = 0}^{m-1} [j + 1 \le \lfloor \frac{ai + b}{c}

[补档计划] 概率论

4.1 事件与概率 在一个黑箱中, 放着 3 个红球和 1 个白球. 我们从箱中取出一个球, 再放回去, 反复进行若干次. 每一次的结果是不确定的, 但总体上拿到红球的次数与拿到白球的次数接近 3 : 1 . 我们发现, 这类现象很常见, 那么我们就要尝试把这类现象的特点进行概括, 命名, 然后研究它的性质, 进而应用它. 概括一下这种现象: 在个别实验中其结果呈现出不确定性, 而在大量重复实验中其结果又具有统计规律性. 为了简便地称呼这种现象, 我们要给它起名字, 称之为 "随机现象"

[补档计划] 字符串

学习一个算法, 需要弄清一些地方: ① 问题与算法的概念; ② 算法, 思维轨迹 ③ 实现, 思维轨迹; ④ 复杂度分析; ⑤ 应用. KMP算法 字符串匹配与KMP算法 为了方便弄清问题, 应该从特例入手. 设 A = " ababababb " , B = " ababa " , 我们要研究下面三个递进层次的字符串匹配问题: ① 是否存在 A 的子串等于 B ② 有几个 A 的子串等于 B ③ A 的哪些位置的子串等于 B KMP算法可以直接在线性复杂度解决问题

[补档计划] 树6 - 莫队算法

[CF633H] Fibonacci-ish II 题意 给定长度为 $N$ 个序列 $A = (a_1, a_2, ..., a_N)$ . $M$ 组询问 $(l, r)$ : 将 $a_l, a_{l+1}, ..., a_r$ 提取出来, 排序, 去重, 得到长度为 $K$ 的序列 $B = (b_1, b_2, ..., b_K)$ , 求 $\sum_{i = 1}^K f_ib_i$ . 其中 $f_i$ 为斐波那契数列的第 $i$ 项: $f_0 = f_1 = 1, f_i =

[补档计划] 覆盖子串与循环节

覆盖子串与循环节的概念 首先还是给覆盖子串和循环节下个定义. 为了方便后面的描述, 我们定义布尔记号 $P_S^T$ , 表示 $T$ 是否为 $S$ 的前缀. 对于一个定义, 为了对它有足够充分的了解, 可以通过多种形式描述这个定义, 这里就再引用图像的方法吧. 再引入前缀记号和后缀记号 pre[i] = S[1 : i], suf[i] = S[1 : |S|]. 对于字符串 S , 若字符串 T , 满足 $P_S^T$ , 且 $\exists k,~P_{kT}^S$ , 则称 T 为

[补档计划] 树4 - 线段树

[CF787D] Legacy 题意 $N$ 个点, $M$ 条连边操作: $1~u~v~w~:~u\rightarrow v$ . $2~u~l~r~w~:~u\rightarrow [l, r]$ $3~u~l~r~w~:~[l, r]\rightarrow u$ . 给定点 $s$ , 求单源最短路. $N\le 10^5$ . 分析 考虑使用 线段树结构 优化 建图. 建立一棵线段树, 每个点表示一个区间. 拆点, 线段树的每个点拆成 入点 和 出点 . 出线段树 的儿子连父亲, 因为可

[补档计划] 树2 - 树上倍增

[SCOI2016] 萌萌哒 题意 求有多少个无前导零的 $N(N\le 10^5)$ 位数 $A$ , 满足 $M(M\le 10^5)$ 个限制条件 $L~R~X~Y$ : $A[L+i] = A[X+i]$ . 分析 区间的信息就先对 ST 表用并查集, 然后下传. 实现 #include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #include <cmat

[补档计划] 动态规划3 - 树形DP

树形DP 是一类 OI 中的问题, 即对一棵树进行 DP . 很多时候要进行两次 DP , 第一次处理子树内的情况, 第二次处理所有的情况. 关键靠做题. [CF697D] Puzzles 题意 给定一棵 $N$ 个节点的树. 求进行 DFS , 每个节点的时间戳的期望值. 分析 树的遍历 & 特性分析 进行 DFS , 根的时间戳一定是 1 . $f[1] = 1$ . $f[next] = f[x] + \sum_{i = 1} ^ c \frac{1}{c} \sum_{son \ne n