SAM详解1

SAM

前言

过于神秘的字符串,但是被同学怂恿,说学会 SAM 就学会了所有字符串算法,心动了过来学,果不其然被创飞了。但研究?天,故余虽愚,终有所获。

由于作者学艺不精,文中可能会有疏漏,如发现错误欢迎指出,那么我们开始旅途吧。

这里是我看的四篇参考文章,质量挺高的:

OI-Wiki

Alex_Wei的博客

command_block的博客

ZTer的博客

1. 一些准备

概论

SAM 的定义:一个长为 n n n 的字符串 s s s 的 SAM 是一个接受 s s s 的所有后缀的最小的有限状态自动机(下文称为自动机)。

对于有限状态自动机,可以理解为一个 DAG,即有向无环图,边上有字母,每走过一条边就相当于带上这个字母,每个节点存储一个或多个字符串。然后这个图有初始节点 P P P 和一个或多个终止节点。其它节点均可从 P P P 出发到达。

SAM 能表示某个字符串的所有子串。

但其实我们只要构造一个含有所有后缀的自动机,其就含有所有子串。

证明很简单,自动机都是一个个字符跳的,如果能跳到这个串,那么也一定经过了所有前缀。

不难有暴力,将原串的所有后缀插到一个字典树中就可以了,但是复杂度 O ( n 2 ) O(n^2) O(n2) 级别,非常不好。

记号

在下文中,字符串的下标从 1 1 1 开始。

  • s i s_i si s [ i ] s[i] s[i] 为字符串 s s s 的第 i i i 位。
  • s [ l , r ] s_{[l,r]} s[l,r] s [ l , r ] s[l,r] s[l,r] 表示 s s s 中下标从 l l l r r r 的子串。
  • n n n ∣ s ∣ |s| s 为字符串 s s s 的长度。

2. e n d p o s \mathrm{endpos} endpos

概述

我们定义一个子串的 e n d p o s \mathrm{endpos} endpos 是它在原串中结束位置的集合。

例如原串为 a b a b c \mathrm{ababc} ababc,则 e n d p o s ( a b ) = { 2 , 4 } , e n d p o s ( c ) = { 5 } \mathrm{endpos(ab)}=\{2,4\},\mathrm{endpos(c)}=\{5\} endpos(ab)={ 2,4},endpos(c)={ 5}

我们把 e n d p o s \mathrm{endpos} endpos 相同的的子串称为一个等价类。如 e n d p o s ( b ) \mathrm{endpos(b)} endpos(b) e n d p o s ( a b ) \mathrm{endpos(ab)} endpos(ab) 相同,它们属于同一个等价类。

下文中用 e d p edp edp 代表 e n d p o s \mathrm{endpos} endpos

性质

然后有一些性质。

下面设两个字符串分别为 s 1 , s 2 s1,s2 s1,s2,且约定 ∣ s 1 ∣ ≤ ∣ s 2 ∣ |s1| \le|s2| s1∣s2∣

引理 2.1 2.1 2.1

s 1 s1 s1 s 2 s2 s2 的后缀 ⟺ e d p ( s 2 ) ⊆ e d p ( s 1 ) \Longleftrightarrow edp(s2)\subseteq edp(s1) edp(s2)edp(s1)

这点显然, s 1 s1 s1 s 2 s2 s2 的后缀,每次出现 s 2 s2 s2 时必定出现 s 1 s1 s1,但出现 s 1 s1 s1 时不一定出现 s 2 s2 s2,得证。

引理 2.2 2.2 2.2

要么有 e d p ( s 2 ) ⊆ e d p ( s 1 ) edp(s2)\subseteq edp(s1) edp(s2)edp(s1),要么有 e d p ( s 2 ) ∩ e d p ( s 1 ) = ∅ edp(s2)\cap edp(s1)=\varnothing edp(s2)edp(s1)=

这点也可以看出,引理 2.1 2.1 2.1 证明了前半部分,对于后半部分考虑反证,若存在 i i i 为公共部分,则可以推出 s 1 s1 s1 s 2 s2 s2 的后缀。不存在这样的 i i i 则可以说明 s 1 s1 s1 不是 s 2 s2 s2 的后缀。所以这个分类正确。

引理 2.3 2.3 2.3

一个等价类中不会包括两个本质不同而长度相同的串。

考虑反证。

假设存在一个等价类 [ s ] [s] [s],其中包含两个本质不同长度相同的串

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值