后缀自动机构造算法学习笔记
作者:互联网
后缀自动机构造算法学习笔记
本文是笔者学习过程中的一些心得体会,不是从入门讲起的,请各位谅解
首先解释一下概念,"后缀自动机"是指的可以识别字符串所有后缀的有限状态自动机。
而我们平时做题用的后缀自动机叫做最简状态后缀自动机。
一个字符串的后缀自动机不唯一,但是最简状态后缀自动机唯一!
后缀自动机的线性构造算法
后缀自动机的构造算法是在线的增量更新。
考虑每次新加入一个字符\(x\),我们需要做的是在保证时空复杂度的基础上构造出新形成的后缀
假设当前的字符串为\(L\),我们列出right集合中含有\(|L|\)的所有状态,设其为\(v_1, v_2, \dots, v_k\)
一个显然的构造思路是我们可以在这些状态后面都加一条\(x\)出边,但是这样的状态数就是\(n^2\)的了。因此我们需要利用之前的状态进行压缩,然而对于不含\(x\)出边的状态,我们仍然需要引出一条\(x\)的出边。
考虑第一个含有\(x\)出边的状态\(p\),在这之后的状态因为表示的都是\(p\)状态的后缀,因此他们也一定含有\(x\)出边。我们考虑想办法用这些出边表示之后的新后缀
接下来就是经典的关于\(len[p]\)与\(len[q]\)的讨论
如果\(len[p] + 1= len[q]\),那么说明\(q\)节点可以作为新的可接受节点,直接把最后添加的节点的father设为q即可
举个例子。
考虑往ab
后面加入字符a
它的SAM会变成这个样子
我们来模拟一下a
加入时的过程
首先从\(3\)引出一条a
边。
接着跳到父亲\(1\)号点,发现其含有a
边连向的节点\(2\),且\(len[2] = len[1] + 1\),那么直接让\(fa[a] = 2\)即可。
这样不会有任何问题。
但是考虑如果是往ab
后面添加b
,它的SAM会变成这样
我们来模拟一下他的添加过程
首先从\(3\)引出一条b
边。
接着跳到父亲\(1\)号点,发现其含有b
边连向的节点\(3\),但是这个时候\(len[3] > len[1] + 1\),说明我们不能直接连接。加入我们连接了会发生什么呢?
这个时候\(3\)号节点会同时表示字符串ab
与b
,显然这两者的right集合是不同的(前者是\(\{2 \}\),后者是\(\{2, 3\}\))
参考资料
标签:状态,后缀,len,算法,出边,自动机,节点 来源: https://www.cnblogs.com/zwfymqz/p/10390319.html