SAM (后缀自动机)
SAM
Intro
Use
Definition
字符串
-
SAM 是一张 DAG。节点被称为 状态,边被称作状态间的 转移。
-
图存在一个源点
,称作 初始状态,其它各节点均可从 出发到达。 -
每个 转移 都标有一些字母。从一个节点出发的 转移 均不同。
-
存在一个或多个 终止状态。如果我们从
出发,最终转移到了一个终止状态,则路径上的所有转移连接起来一定是 的一个后缀。 的每个后缀均可用一条从 到某个终止状态的路径构成。 -
在所有满足上述条件的自动机中,SAM 的结点数是最少的。
Demonstration
endpos (结束位置)
Definition
endpos
对于
规定字符串从
等价类
两个子串
这样所有
Property
Lemma 1
Lemma 1 (endpos)
字符串
的两个非空子串 和 (假设 )的 相同,当且仅当字符串 在 中的每次出现,都是以 的后缀的形式存在的。
Lemma 2
Lemma 2 (endpos)
考虑两个非空子串
和 (假设 )。则:
Lemma 3
Lemma 3 (endpos)
考虑一个
等价类,将类中所有子串按长度非递增的顺序排序。每个子串都不会比它前一个子串长,与此同时每个子串也是它前一个子串的后缀。换句话说,对于同一等价类的任一两子串,较短者为较长者的后缀,且该等价类中的子串长度恰好覆盖整个区间 。 其中
表示最短子串长度, 表示最长子串长度。
Link (后缀链接)
Intro
考察 SAM 中某个不是
将
并且至少有一个
设
状态的本质就是重要的转折子串。
Property
Lemma 4
Lemma 4 (link)
所有后缀链接构成一棵根节点为
的树。
Lemma 5
Lemma 5 (link)
通过
集合构造的树(每个子节点的子集都包含在父节点的子集中)与通过后缀链接构成的树相同。
Demonstration
Algorithm
SAM 是一个 在线 算法。
大致方法是:逐个加入 字符,对应维护 SAM。
一开始 SAM 只包含一个状态
现在,任务转化为实现给当前字符串添加一个字符
- 令
为添加字符 之前,整个字符串对应的状态(一开始我们设 ,算法的最后一步更新 )。 - 创建一个新的状态
,并将 赋值为 ,在这时 的值还未知。 - 现在我们按以下流程进行(从状态
开始)。如果还没有到字符 的转移,我们就添加一个到状态 的转移,遍历后缀链接。如果在某个点已经存在到字符 的转移,我们就停下来,并将这个状态标记为 。 - 如果没有找到这样的状态
,我们就到达了虚拟状态 ,我们将 赋值为 并退出。 - 假设现在我们找到了一个状态
,其可以通过字符 转移。我们将转移到的状态标记为 。 - 现在我们分类讨论两种状态,要么
,要么不是。 - 如果
,我们只要将 赋值为 并退出。 - 否则就会有些复杂。需要 复制 状态
:我们创建一个新的状态 ,复制 的除了 的值以外的所有信息(后缀链接和转移)。我们将 赋值为 。
复制之后,我们将后缀链接从 指向 ,也从 指向 。
最终我们需要使用后缀链接从状态 往回走,只要存在一条通过 到状态 的转移,就将该转移 重定向 到状态 。 - 以上三种情况,在完成这个过程之后,我们将
的值更新为状态 。
上面是贺的 OI-wiki 的讲解。没有图怎么行呢?!
Demonstration
之前那些图是贺的,接下来我亲自画。假设要对
下面这张图有点小问题:3 号节点有两个后缀链接。
就是对于
实际操作很简单嘛,就是赋值。
最后是完整的 SAM:
一个下午.past. QWQ 手残+强迫症
本文作者:Schucking-Sattin
本文链接:https://www.cnblogs.com/Schucking-Sattin/p/16544548.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步