这玩意真的是坑啊,看了很多博客都没弄懂,课业繁忙,断断续续搞了三天才刚明白大意。。。
定义介绍:
给定字符串str,建立后缀自动机
后缀自动机是什么?其实就是前缀树的压缩,存一个图的前缀树所耗费的空间太大了,我们利用字符串各个子串之间的关系去掉一些没必要出现的结点,后缀自动机有一个根节点,每次从根结点出发,到任意一个结点结束所形成的一个字符串都是str的子串
sam(str):表示字符串str的后缀自动机
endpos(有些地方是right集合)
指一个字符串s在str中出现的位置构成的集合,使用字符串s的结尾字母在str的位置代表字符串在str的位置
例:str="ABBBCDBCECG"
字符串"BC"的endpos:"5、8";字符串"C"的endpos:"5、8、10";字符串"AB"的endpos:"2"
关于endpos的一些性质:
1、endpos相同的两个字符串,其中一个一定是另一个的后缀
2、如果字符串a是字符串b的后缀,b的endpos一定是a的endpos的子集
3、对于一些endpos相同的字符串,它们一定互为后缀,且它们的长度连续
4、确定了endpos和len就能确定唯一的一个字符串
trans状态转移函数
状态state(xx):表示一个字符串集合,这个集合中的字符串的endpos都是xx(xx是一个endpos)
表示:当前状态是s,在其后加上一个字符c后到达状态p
状态s中的任意字符串在其后加上字符c后得到的endpos都是相同的,即都指向状态p
Parent、Parent树
shortest:状态s中字符串长度最小的一个字符串
longest:状态s中字符串长度最大的一个字符串
性质:
1、对于状态s中的shortest的任意一个后缀(不包括自己)的状态p,则有:s的endpos是p的endpos的真子集
2、状态s的shortest去掉首字母后得到的字符串一定是另一个状态的longest,这个状态我们定义为Parent状态,简记为pa状态
3、我们可以得到公式:
4、s的endpos是其pa的endpos的真子集
5、如果trans(s,c)≠NULL,那么,trans(pa,c)≠NULL;因为如果trans(s,c)存在这个状态,那么pa的字符串加上字符c之后,一定 还是状态s+c的后缀,所以也一定存在trans(pa,c),所以,你可以认为状态pa完全包含状态s
6、状态pa的endpos就是它所有儿子的状态的endpos的并集
对于字符串:"ABCDBCDD"
构造后缀自动机
后缀自动机中的结点:指一个状态(字符串的集合):state(endpos(ss))(ss为从root结点到当前结点所形成的最长字符串)
知道了这些以后,我们怎么构造出str的后缀自动机呢?
我们是根据状态转移函数在线构造的,从str的首字符开始,依次添加字符进行构造,所以现在重要的是怎么进行转移的?
假设我们已经构造出sam(T),怎么构造出sam(Tx)呢?
sam(Tx)比sam(T)多了字符串Tx的所有的后缀,这些后缀都是由T的后缀+字符x转移来的(除了字符x本身,可另做考虑),所以我们要想办法找出这些结点,使得这些结点能表示出所有的这些后缀,然后把这些结点与新结点相连即可