专栏文章
一些对于SAM的理解
算法·理论参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqf4cb4
- 此快照首次捕获于
- 2025/12/04 03:46 3 个月前
- 此快照最后确认于
- 2025/12/04 03:46 3 个月前
对于构造需要满足的要求就先省略了。
如果不考虑时空限制的话,后缀Trie是一个很方便的实现方式,但是其时空复杂度都是 的,并不是很能接受。
有两个方向:
- 把转移压缩(字符转移变为字串转移),这个对应后缀树。
- 压缩状态(找到等价类进行划分),这个对应后缀自动机。
现在我们考虑第二种优化方法,这时我们引入 endpos 的概念,我们用 表示字符串 在字符串 中出现的所有位置的末位置的集合, endpos 集合相同的子串归为一个等价类。这一定义能带来很多优秀的性质,比较重要的包括:
- 对于两个子串 和 , 与 的关系只有包含或并列两种可能,绝对不会相交。
- 一个等价类中的子串长度连续。
- 等价类的数量是 级别的。
第三点的证明可以用一种叫做 parent tree 的树,实际上就是根据第 1 条的性质画出的树结构,并且这种结构保证状态数在 级别。
但我认为最巧妙的是后缀自动机的构造,这是一个在线的过程,看起来很不可思议,每动态插入一个字符,就相当于加入一堆新后缀,就要新接许多转移边,就会导致一系列等价类集合更新,似乎不是很能做到快速更改。
然后这里就一直不是很能理解,后来在某处看到了自动地这个词,突然领悟了一些。
我们从来没有维护过 endpos 集合的具体位置,为什么呢,因为这个集合是会自动更新的,当你进行插入时,它就已经改变了,并不需要手动修改。
然后再回过头来看插入操作,最长的那个串 一定会形成一个新的等价类 ,而 一路往上跳,如果都不存在到新字符 的转移边,那么这些新形成的子串的 endpos 集合均为 ,显然是从空集引出的,所以新节点的 指向源点。假如一路跳到了头,那么就只产生了这个新状态,而转移边已经全连上了。
如果上跳过程中存在一个位置 且 有 这条转移边,转移到了 ,那么很明显,由 转移到的 的 endpos 集合中会自动加入 这一元素,但是,不一定只有 能转移到 。因此我们要进行讨论:
- 只有 转移到 (此时 ),直接在 的 endpos 集合中插入 即可,不用进行进一步修改,那我们也只需要将新节点的 指向 即可完成修改,因为 再向上跳的类中都已经自动加入了 这一元素,并不需要我们再沿 跳上去进行修改了,另一种情况也是同理的。
- 不只有 转移到 ,显然需要一个全新的等价类,我们直接新创建一个等价类 ,很显然地, 和从 继续往上跳的且能转移到 的点,都会指向新建节点 ,因为这才是它们转移到的等价类,而原来 所代表的 endpos 集合就成为了 的真子集,根据定义 自然要指向 ,新节点的 也同理,由于只新增了一个字符,那么加入一个不同字符的转移一定不会有以 位置为结尾的后缀,如果存在,那么一定是形如
aaaaa的串,但很显然这会被情况 1 处理掉,所以 的所有转移放在 上全部成立,至于 的 ,由于只有 及其往上跳的部分点会转移到 ,所以自然是 。
那么至此插入的三种情况全部解决,只需要把 改为新节点的编号就行,插入过程就圆满完成了。
这算是我对后缀自动机的理解过程吧,状态数证明和一些细节的证明还没有深入探究,以后再继续深入。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...