后缀自动机是用于识别子串的自动机

学习推荐:陈立杰讲稿,本文记录重点部分和感性理解(论文语言比较严格)。

刷题推荐:[后缀自动机初探],题目都来自BZOJ。

【Right集合】

后缀自动机真正优于后缀树的方面在于:结合了有限状态自动机,从而实现了O(n)的时空复杂度。

trans(s,str)表示s+str到达的状态。

ST(str)=trans(init,str)即包括了str这一子串的唯一状态(一个子串只能属于一个状态)

定义字符串a在S中出现的右端点位置集合Right(a)=r1,r2...rn

SAM中一个状态s的Right集合为Right(s),那么状态s表示所有[Right(a)=Right(s)的子串a],那么实际上状态s表示的子串a的长度在一个区间内,记作[Min(s),Max(s)]。字符串越短,Right集合越大。

容易证明对于任意状态a和b,Right(a)和Right(b)要么包含要么不相交。(很显然的结论,只是论文的证明比较严格化)

★在后缀自动机中,一个状态s(或称“节点s”)表示的是Right(a)=Right(s)的若干子串a,其长度区间为[MIn(s),Max(s)],从而达到状态数O(n)的目的。

Right集合形成的树形包含关系称为Parent Tree,树边由孩子指向父亲,是SAM中的失配边。

Parent树从上往下,子串长度扩大,Right集合变小,父节点的Right集合包含子节点的Right集合

fa=Parent(s)当且仅当fa是使Right(fa)最小且满足Right(s)⊂Right(fa)的结点,(从儿子到父亲,就是子串稍微缩短,Right集合变大)

另有Max(fa)=Min(s)-1,实质上是要求fa和s之间没有一个Right子集x满足Right(s)⊊Right(x)⊊Right(fa)。

【线性构造SAM】

线性构造采用增量法,即已知字符串T的SAM(T),L=Len(T),在末尾加入字符x,构造SAM(Tx),转移如下:

①实边转移规则:t=trans(s,x)表示s--->t标号为x的边,若Right(s)={r1,r2...rn},则Right(t)={ri+1|s[ri+1]=x}

②虚边转移规则:Parent树边满足Right(s)⊊Right(fa),Max(fa)=Min(s)-1(含义如上所述)

加入x,考虑所有Right集合包含L的结点v1,v2...vk,显然它们在Parent树上是一条从根到叶子的链。

定义叶子结点v1=p=ST(T)(即p代表整个串),Right(p)={L},不妨它们从后代到祖先排为v1=p...vk=root。

同时新建结点np=ST(Tx),Right(np)={L+1}。

考虑节点v,Right(v)={r1,r2...rn=L}

根据转移规则①,如果除了rn外不存在S[ri+1]=x,那么节点v不存在trans(v,x)。

根据转移规则②,越往上Right集合逐渐扩大直至节点vp存在trans(vp,x),那么v1~vp-1只须向np连出标号为x的边(np=trans(v,x)),而vp~vk都已经存在trans(v,x)。

令trans(vp,x)=q,当Max(q)=Max(vp)+1时,只须在q的Right集合中插入L+1。

下面重点讨论Max(q)>Max(vp)+1的情况。

eg.

T+x:aaabcaaabcaa+b

vp:aaabcaaabcaa  Max(vp)=2

q:aaabcaaabcaa   Max(q)=4

根据实边的转移规则,实际上节点q不止由vp转移过来,也由vp在Parent树上的儿子o转移过来(多条实边连入):

o:aaabcaaabcaa  Max(o)=3

可见,o才满足Max(q)=Max(o)+1。trans(vp,b)形成了aab,而trans(o,b)形成了aaab,由于有限状态自动机的性质Right(aab)=Right(aaab)所以合并成同一个点p。

但是当末尾+b时,我们发现Right(aab)>Right(aaab)也就是出现了新的Right集合aab——Right(aab)=Right(q)+Right(np),所以创造新的节点nq:

nq:aaabcaaabcaab  Max(nq)=3

Right(nq)实际上是Right(q)和Right(parent(q))夹出来的新Right集合(aab之前被并入q现在分离出来),并且vp将改为连向nq。

vp的祖先中连向q的部分要改为连向nq,因为这些点连向q说明+x后Right集合=Right(q),那么现在就要连向nq。

线性构造SAM的具体步骤如下:

1.新建np,找到vp,vp之前的点连向np。若不存在vp则fa(np)=-1。

2.若len(q)=len(vp)+1,fa(np)=q,结束。

3.len(q)>len(vp)+1,新建节点nq复制q信息并修改len。

4.从vp到根若连向q改为nq。

void insert_SAM(int c){
int np=++size;
t[np].len=t[last].len+;
int x=last;
last=np;
while(x&&!t[x].t[c])t[x].t[c]=np,x=t[x].fa;
if(!x)t[np].fa=root;else{
int y=t[x].t[c];
if(t[y].len==t[x].len+)t[np].fa=y;else{
int nq=++size;
t[nq]=t[y];//
t[nq].len=t[x].len+;
t[nq].fa=t[y].fa;t[y].fa=t[np].fa=nq;
while(x&&t[x].t[c]==y)t[x].t[c]=nq,x=t[x].fa;//
}
}
} last=size=root=;
for(int i=;i<=m;i++)insert_SAM(s[i]-'a');

注意:后缀自动机节点数是2n。

【技巧和应用】

后缀自动机没有高论,本质上仅仅是识别子串的自动机,为了压缩时空复杂度将Right集合相同的子串集合作为一个节点,然后构造自动机的一般属性:trans边(实边)和fail边(虚边)。

1.节点的本质:每个节点是Right集合,是Right集合相同的子串集合。

2.实边:后接字符。

从x的某个子串后面+一个字母,能够得到y的某个子串。(所以从根沿子串走能得到子串所在节点)

3.虚边:前删字符。(匹配失败fail)

删除最少的字符使得Right集合变化。故该串在Parent树上的祖先都是该串的后缀。

1.Right集合:SAM中每个节点是right集合。

每次的np称为“关键节点”,这个节点的最长字符串是以该Right点结尾的前缀。(它最终不一定是叶子)。

Right集合大小:np值为1,按Parent树建边进行dfs统计即可。Right集合大小就是每个状态代表串的出现次数

例题:【BZOJ】3998: [TJOI2015]弦论

统计Right集合具体的话可以用线段树合并或set启发式合并。

实边:每个节点x连出实边y相当于在串s(x)后+x到达另一个节点(right尽可能大),这个到达的节点串的前面可能会延伸。

每一条从根到节点的路径都是一个子串对应的状态。虚边:连接右端点位置相同而长度不同子串,该串在Parent树上的祖先都是该串的后缀,这就可以用来作为fail树。)

4.匹配:一个串从自动机根节点往下沿实边走并cnt++,不能走就沿虚边fail至能继续走的点y(cnt=len(y)+1),然后往下走。因为Parent的父亲一定是后缀,这样能识别出这个串和SAM的以每个位置结尾的最长公共子串的节点。这些识别点在Parent树上的所有祖先节点合起来就是所有公共子串。

例题:【BZOJ】4032: [HEOI2015]最短不公共子串(LibreOJ #2123)

5.后缀树:对逆序串建立SAM,parent树就是原串的后缀树,后缀的LCP就是后缀树上两个np的LCA。

例题:【BZOJ】3238: [Ahoi2013]差异

6.找到指定串节点:在Parent上从对应右端点位置的“前缀开端节点”倍增到Len合适的位置。

例题:【BZOJ】3676: [Apio2014]回文串

7..子串数:对每个点x,Max(x)-Max(fa(x))得到的就是该点的长度区间即子串数,所有点的子串数就是子串总数。

【算法专题】后缀自动机SAM的更多相关文章

  1. 【算法】后缀自动机(SAM) 初探

    [自动机] 有限状态自动机的功能是识别字符串,自动机A能识别字符串S,就记为$A(S)$=true,否则$A(S)$=false. 自动机由$alpha$(字符集),$state$(状态集合),$in ...

  2. 【算法】后缀自动机(SAM) 例题

    算法介绍见:http://www.cnblogs.com/Sakits/p/8232402.html 广义SAM资料:https://www.cnblogs.com/phile/p/4511571.h ...

  3. [转]后缀自动机(SAM)

    原文地址:http://blog.sina.com.cn/s/blog_8fcd775901019mi4.html 感觉自己看这个终于觉得能看懂了!也能感受到后缀自动机究竟是一种怎样进行的数据结构了. ...

  4. SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)

    1811. Longest Common Substring Problem code: LCS A string is finite sequence of characters over a no ...

  5. 后缀自动机(SAM)奶妈式教程

    后缀自动机(SAM) 为了方便,我们做出如下约定: "后缀自动机" (Suffix Automaton) 在后文中简称为 SAM . 记 \(|S|\) 为字符串 \(S\) 的长 ...

  6. 后缀自动机SAM学习笔记

    前言(2019.1.6) 已经是二周目了呢... 之前还是有一些东西没有理解到位 重新写一下吧 后缀自动机的一些基本概念 参考资料和例子 from hihocoder DZYO神仙翻译的神仙论文 简而 ...

  7. 浅谈后缀自动机SAM

    一下是蒟蒻的个人想法,并不很严谨,仅供参考,如有缺误,敬请提出 参考资料: 陈立杰原版课件 litble 某大神 某大神 其实课件讲得最详实了 有限状态自动机 我们要学后缀自动机,我们先来了解一下自动 ...

  8. 后缀自动机(SAM)速成手册!

    正好写这个博客和我的某个别的需求重合了...我就来讲一讲SAM啦qwq 后缀自动机,也就是SAM,是一种极其有用的处理字符串的数据结构,可以用于处理几乎任何有关于子串的问题,但以学起来异常困难著称(在 ...

  9. 【文文殿下】对后缀自动机(SAM)的理解

    后缀自动机,是一种数据结构,是由状态和转移关系构成的.它虽然叫做后缀自动机,可是他却与后缀并没有什么太大的联系. 后缀自动机的每一种状态都是原串的一些子串的集合,每个子串只唯一存在于某个状态中,对每一 ...

随机推荐

  1. Beta阶段DAY2

    一.提供当天站立式会议照片一张 二.每个人的工作 1.讨论项目每个成员的昨天进展 刘阳航:删除多余按钮,调整界面. 林庭亦:删除麻烦的颜色设置. 郑子熙:添加新增按钮. 陈文俊:重新规划面板及功能. ...

  2. [转帖]IBM POWER9 E950 and E980 Servers Launched

    IBM POWER9 E950 and E980 Servers Launched https://www.servethehome.com/ibm-power9-e950-and-e980-serv ...

  3. [C/C++] C++ Primer学习笔记

    记录下自己掌握不清楚的概念和用法... Day 1 endl:具有输出换行的效果,并刷新与设备相关联的缓冲区. 注:在调试程序过程中插入的输出语句都应刷新输出流,否则可能会造成程序崩溃,将会导致程序出 ...

  4. SQL查找删除重复行

    本文讲述如何查找数据库里重复的行.这是初学者十分普遍遇到的问题.方法也很简单.这个问题还可以有其他演变,例如,如何查找“两字段重复的行”(#mysql IRC 频道问到的问题) 如何查找重复行 第一步 ...

  5. Java中LinkedList的fori和foreach效率比较

    在<Java中ArrayList的fori和foreach效率比较>中对ArrayList的两种循环方式进行了比较,本次对LinkedList的两种遍历方式进行效率的比较. 1. list ...

  6. 《编写高质量代码改善JavaScript程序的188个建议》读书笔记

    逗号运算符比较怪异.如    var a =(1,2,3,4);alert(a);// 4      var a = 1,2,3,4;//报错 注意a++和++a的差别,变量在参与运算中不断地变化.v ...

  7. spring通过工厂模式解决页面耦合问题

    spring通过工厂模式解决页面耦合问题

  8. 【Java】提取JSON数值时遇到数组集合时使用的K-V方式转换

    1.实体类转换方法 参照文章:http://www.cnblogs.com/dflmg/p/6933811.html 2.K-V方法(此方法比较笨,但是没有办法,我现在不知道有没有相关的简单API,只 ...

  9. java 连接mysql增删改查

    1.创建mysql测试表 2.按下图创建3个文件夹与3个类 3.三个类的代码 PersionDao :目录(Data Access Object), 数据访问对象是第一个面向对象的数据库接口 pack ...

  10. BZOJ4727 [POI2017]Turysta 【竞赛图哈密顿路径/回路】

    题目链接 BZOJ4727 题解 前置芝士 1.竞赛图存在哈密顿路径 2.竞赛图存在哈密顿回路,当且仅当它是强联通的 所以我们将图缩点后,拓扑排序后一定是一条链,且之前的块内的点和之后块内的点的边一定 ...