后缀自动机详解

当想让学妹看博客时,怕旧的写的太烂被嫌弃,又怕新的看不懂……哎

一、定义:

单词的有向无环图

二、作用

从原点出发形成的所有路径即为单词的所有子串,并且通过维护endpos和endpos类,得知每个串出现的次数和出现的位置

三、构建后缀自动机

一些性质:

  1. endpos :数集,一些子串他们出现的位置相同,这些位置的集合称为endpos

  2. endpos类 :串集,一些子串他们出现的位置相同,这些子串的集合称为endpos类

  3. fail树

  • 树上节点的endpos是他父亲节点endpos的真子集

  • 树上节点的父亲包含的子串是当前节点包含的子串的后缀

  • 树上节点的endpos类中的子串长度连续

  • 树上节点的endpos类中的最小长度等于他父亲节点endpos类中的最长长度+1

后缀自动机维护的东西:

  1. fail树上的父亲

  2. c边连向的点

  3. endpos类中最长串的长度

以上是一些概念,由他的性质和用途决定,就像1+1=2一样解释不了,早出生一点也许就不这样了呢

这些概念性的东西介绍完毕之后,就要开始讲如何维护了

考虑每次新添加一个字符进后缀自动机中(新开一个节点),改变的只有未添加新字符的所有后缀,就相当于在原来的终止节点后添加一个字符,长度+1,且每个终止节点都要向他引出一个c边,而由性质我们可以知道当前终止节点的所有祖先既终止节点集,当最终跳到源点的时候就表示,旧串中没有新形成的字符串的后缀,说明没有节点会发生改变,所以新节点的父亲指向1就可以了,所那么如下代码的意义就解释完毕:

int preNode = lastNode;
int nowNode = lastNode = ++tot;
mac[nowNode].len = mac[preNode].len+1;
for(;preNode&&!mac[preNode].ch[c];preNode = mac[preNode].fa) mac[preNode].ch[c] = nowNode;
if (!preNode) mac[nowNode].fa = 1;

如果旧串中存在新形成的字符串的后缀呢?那么说明现在的preNode之前的节点会发生改变,额……待我仔细斟酌一下再下笔,毕竟要吃饭了

上一篇:后缀自动机总结


下一篇:后缀三姐妹 笔记