后缀自动机_SAM学习大记
2017-12-21 12:27
148 查看
刷新了我对难懂算法的定义,下面都是自己的一些粗浅理解
参考资料:后缀自动机详解 http://blog.csdn.net/qq_35649707/article/details/66473069
陈立杰冬令营讲稿 https://wenku.baidu.com/view/90f22eec551810a6f4248606.html
2) 是一张dag,其中点被称为状态,边被称为转移,每个转移都有一个标号(字母集中的一个元素) ,某一状态t_0被称作初始状态,由它能够到达其余所有状态。
3) 从一个状态出发不能有两个相同标号的转移
4) 一个或多个状态被标记为终止状态。如果我们从初始状态t_0经由任意路径走到某一终止状态,并顺序写出所有经过边的标号,你得到的字符串必然是s的某一后缀。 也就是说s的所有子串都能被这样类似地表达出来,而且内容相同的子串的表达路径是同一条.
定义: endpos(v)表示字符串v在s中出现终点(右端点)集合. endpos(t0)=全集
1) 具有相同endpos集合的子串被称为在同一个等价类中(动机: 可以转移到的后缀相同)
2)一个状态,即一个点,表示的是某个endpos集合(某等价类)。一个子串属于该等价类,当且仅当这个子串是t0到该点的一条路径.
重要: 3)两个合法endpos集合要么是包含关系,要么不相干. 易反证.
4)某一终点等价类中的字符串互为后缀,它们的长度依次取区间[x,y]内的所有数。
证明: 若长度为x与y的都属于该等价类,那么长度处于他们之间的也显然属于它.
5)若状态x有转移(x,t),则可以判断:该endpos集合中的某些位置后面有一个c,从而可以加一个字符,转移到一个新的endpos. 并不是所有位置后面都有c。
反过来,若endpos中某些位置后面有c,则这个状态一定有一个标号为c的转移.
(建议与定义4最后一句话一起理解)
看懂上面的之后,换句话说:一个等价类有(x,t)转移,不意味着在其中的所有字符串都可以加c,而是一部分可以加c.
后缀自动机可以被看作:
s的所有子串可以按照它们的终点集合被分成等价类。
后缀自动机由一个初2始状态t_0和所有不同的终点等价类所对应的状态以及他们之间的转移组成。
定义:link(x)表示对于某个endpos集合x(状态x),包含他并且endpos集合大小最小的状态. (就是比他稍微大一点点的那个endpos集合)
link链:顺着link一直走直到t0,所到达的点集.
link链组成了一棵以t_0为根的树。
证明.考虑任意状态v≠t_0.后缀链接link(v)指向的状态所对应的字符串长度严格小于它本身(根据定义)
因此,沿着后缀链接移动,我们将早晚到达t_0,它对应一个空串。
6)若等价类x中的字符串长度区间为[x,y] (见4),link(x)中的字符串长度集合应为[z,x-1]
解释:就相当于随着字符串长度不断减小(要求不断放宽),endpos一点点变大.
7)顺着link(x)走实际上就是在扩展endpos集合. (串的要求逐渐放宽)
8)x的link链 就是 所有包含了x的endpos集.(endpos一点点变大,直到全集,又综合3可感性得出此结论)
推论: 若等价类x包含了等价类y,那么y 一定 在x的link链上 。
定义:对于一个等价类x,len(x)是在他之中的最长字符串长度.
对于串s我们有构造好的自动机,并且全串s所对应的状态是last.
(显然last的endpos集合只有一个元素:s的长度,因此)
1) 考虑新插入一个字符c. 必须要新建一个状态cur,endpos={s+c末尾位置},
因此len(cur)=len(last)+1=s+c长度
2) 因为s的后缀所在的endpos全在last的link链上(因为他们全部包括s的末尾位置),需要为他们添加转移c以接收新串的所有后缀
因此从last开始顺着last的link链往上走,当前点x若没有转移c则为他添加一条(x,cur)标号为c的转移,
走到t0 或 遇到一个点有标号为c的转移则停止.
若走完,仍没有任何一个点有标号为c的转移(t0也没有),则将link(cur)设为t0
(因为t0也没有c的转移,显然没有包含cur的endpos了),结束过程
3) 设遇到第一个有转移c的点为x,并且这条转移是(x,t);首先len(t)>len(x),因为根据转移,len(t)至少等于len(x)+1
因为不能为他直接添加新的转移,我们考虑可不可以为点c的endpos集合添加s+c这个位置,并在link与len中做出对应更新呢?(其实endpos集合都是假想的,实际上并不需要对于每个点保存)
红色框框为在此endpos中在最长的串,由于(x,t),因此t的endpos集合应该比x往后挪一位,并且更小.
重要:
我们现在给t添加s+1这个位置,会发现po这一段不一定和前面两个endpos中的元素中对应位置匹配。
但有一种情况可以使得po长度为0,也就是len(t)=len(x)+1
当这种情况时,我们假想为t添加s+1,并可以直接将link(cur)赋值为t,并结束过程。
将link(cur)设为t之后相当于为t的link链上的endpos都添加s+1(这关系到endpos集合的求法,见参考文章的应用部分),并且t是endpos大小最小的,因此link(cur)指向t.
还有一个疑问:为什么能结束过程,而不用继续为后面的点添加转移?见性质5,后面的点都是x代表的串的后缀,所以它们加一个c得到的一定是t所代表的串的后缀,因此在t的link链上
现在来解决一般情况:len(t)>len(x)+1
原因: 在等价类x中,长度不超过len(t)+1的串的endpos集合会多s+1这个元素,而其他不会。 因此该等价类分裂为两个等价类:
新建点nt ,根据原因,len(nt)=len(x)+1;
除此之外,t的所有数据全部复制给nt.然后再调整link,nt的endpos集合是endpos(t)+(s+1),正好比endpos(t)大一点点,所以link(t)=nt(nt的endpos集合合法,因此由定理3得这样连没有问题)
将x的link链(包括x)上连到t的转移全部改成连到nt上。 (如果遇到c的转移一个不是t的就不用继续改下去,因为它转移的在nt的link链上)
最后link(cur)=nt.
无论何时退出,last都应该更新为cur.
抛开构造不看,因为点数不超过2len.
所以几乎所有操作复杂度都是O(n)的。
问题就是要证明构造也是O(n)的。
题目: 4072. 【TJOI2015】弦论(string)
size(endpos) 就是link链组成的树中子树的大小.
也可理解成加点时(拆点时不计),对当前link链上所有点+1
参考资料:后缀自动机详解 http://blog.csdn.net/qq_35649707/article/details/66473069
陈立杰冬令营讲稿 https://wenku.baidu.com/view/90f22eec551810a6f4248606.html
定义
1) 可以接收串S的所有后缀的最简状态自动机2) 是一张dag,其中点被称为状态,边被称为转移,每个转移都有一个标号(字母集中的一个元素) ,某一状态t_0被称作初始状态,由它能够到达其余所有状态。
3) 从一个状态出发不能有两个相同标号的转移
4) 一个或多个状态被标记为终止状态。如果我们从初始状态t_0经由任意路径走到某一终止状态,并顺序写出所有经过边的标号,你得到的字符串必然是s的某一后缀。 也就是说s的所有子串都能被这样类似地表达出来,而且内容相同的子串的表达路径是同一条.
基本认知 (若干定理) 必看
较多感性理解,如不适则请移步相关论文,课件.定义: endpos(v)表示字符串v在s中出现终点(右端点)集合. endpos(t0)=全集
1) 具有相同endpos集合的子串被称为在同一个等价类中(动机: 可以转移到的后缀相同)
2)一个状态,即一个点,表示的是某个endpos集合(某等价类)。一个子串属于该等价类,当且仅当这个子串是t0到该点的一条路径.
重要: 3)两个合法endpos集合要么是包含关系,要么不相干. 易反证.
4)某一终点等价类中的字符串互为后缀,它们的长度依次取区间[x,y]内的所有数。
证明: 若长度为x与y的都属于该等价类,那么长度处于他们之间的也显然属于它.
5)若状态x有转移(x,t),则可以判断:该endpos集合中的某些位置后面有一个c,从而可以加一个字符,转移到一个新的endpos. 并不是所有位置后面都有c。
反过来,若endpos中某些位置后面有c,则这个状态一定有一个标号为c的转移.
(建议与定义4最后一句话一起理解)
看懂上面的之后,换句话说:一个等价类有(x,t)转移,不意味着在其中的所有字符串都可以加c,而是一部分可以加c.
后缀自动机可以被看作:
s的所有子串可以按照它们的终点集合被分成等价类。
后缀自动机由一个初2始状态t_0和所有不同的终点等价类所对应的状态以及他们之间的转移组成。
定义:link(x)表示对于某个endpos集合x(状态x),包含他并且endpos集合大小最小的状态. (就是比他稍微大一点点的那个endpos集合)
link链:顺着link一直走直到t0,所到达的点集.
link链组成了一棵以t_0为根的树。
证明.考虑任意状态v≠t_0.后缀链接link(v)指向的状态所对应的字符串长度严格小于它本身(根据定义)
因此,沿着后缀链接移动,我们将早晚到达t_0,它对应一个空串。
6)若等价类x中的字符串长度区间为[x,y] (见4),link(x)中的字符串长度集合应为[z,x-1]
解释:就相当于随着字符串长度不断减小(要求不断放宽),endpos一点点变大.
7)顺着link(x)走实际上就是在扩展endpos集合. (串的要求逐渐放宽)
8)x的link链 就是 所有包含了x的endpos集.(endpos一点点变大,直到全集,又综合3可感性得出此结论)
推论: 若等价类x包含了等价类y,那么y 一定 在x的link链上 。
定义:对于一个等价类x,len(x)是在他之中的最长字符串长度.
线性构造算法(顺序看下去)
对每一状态,需要维护两个基本值:link与len.对于串s我们有构造好的自动机,并且全串s所对应的状态是last.
(显然last的endpos集合只有一个元素:s的长度,因此)
1) 考虑新插入一个字符c. 必须要新建一个状态cur,endpos={s+c末尾位置},
因此len(cur)=len(last)+1=s+c长度
2) 因为s的后缀所在的endpos全在last的link链上(因为他们全部包括s的末尾位置),需要为他们添加转移c以接收新串的所有后缀
因此从last开始顺着last的link链往上走,当前点x若没有转移c则为他添加一条(x,cur)标号为c的转移,
走到t0 或 遇到一个点有标号为c的转移则停止.
若走完,仍没有任何一个点有标号为c的转移(t0也没有),则将link(cur)设为t0
(因为t0也没有c的转移,显然没有包含cur的endpos了),结束过程
3) 设遇到第一个有转移c的点为x,并且这条转移是(x,t);首先len(t)>len(x),因为根据转移,len(t)至少等于len(x)+1
因为不能为他直接添加新的转移,我们考虑可不可以为点c的endpos集合添加s+c这个位置,并在link与len中做出对应更新呢?(其实endpos集合都是假想的,实际上并不需要对于每个点保存)
红色框框为在此endpos中在最长的串,由于(x,t),因此t的endpos集合应该比x往后挪一位,并且更小.
重要:
我们现在给t添加s+1这个位置,会发现po这一段不一定和前面两个endpos中的元素中对应位置匹配。
但有一种情况可以使得po长度为0,也就是len(t)=len(x)+1
当这种情况时,我们假想为t添加s+1,并可以直接将link(cur)赋值为t,并结束过程。
将link(cur)设为t之后相当于为t的link链上的endpos都添加s+1(这关系到endpos集合的求法,见参考文章的应用部分),并且t是endpos大小最小的,因此link(cur)指向t.
还有一个疑问:为什么能结束过程,而不用继续为后面的点添加转移?见性质5,后面的点都是x代表的串的后缀,所以它们加一个c得到的一定是t所代表的串的后缀,因此在t的link链上
现在来解决一般情况:len(t)>len(x)+1
原因: 在等价类x中,长度不超过len(t)+1的串的endpos集合会多s+1这个元素,而其他不会。 因此该等价类分裂为两个等价类:
新建点nt ,根据原因,len(nt)=len(x)+1;
除此之外,t的所有数据全部复制给nt.然后再调整link,nt的endpos集合是endpos(t)+(s+1),正好比endpos(t)大一点点,所以link(t)=nt(nt的endpos集合合法,因此由定理3得这样连没有问题)
将x的link链(包括x)上连到t的转移全部改成连到nt上。 (如果遇到c的转移一个不是t的就不用继续改下去,因为它转移的在nt的link链上)
最后link(cur)=nt.
无论何时退出,last都应该更新为cur.
复杂度分析
2018/1/5 UPD::抛开构造不看,因为点数不超过2len.
所以几乎所有操作复杂度都是O(n)的。
问题就是要证明构造也是O(n)的。
应用部分
1.求endpos集合大小题目: 4072. 【TJOI2015】弦论(string)
size(endpos) 就是link链组成的树中子树的大小.
也可理解成加点时(拆点时不计),对当前link链上所有点+1
相关文章推荐
- 【hihoCoder 1466】后缀自动机六·重复旋律9
- hiho一下第130周 后缀自动机二·重复旋律7
- [后缀自动机 构建后缀树 树形DP] BZOJ 3238 [Ahoi2013]差异
- [BZOJ3238][Ahoi2013][后缀自动机][树形DP]差异
- BZOJ 1396&&2865 识别子串[后缀自动机 线段树]
- SPOJ Lexicographical Substring Search 后缀自动机
- 【Codeforces666E】Forensic Examination 后缀自动机 + 线段树合并
- BZOJ 2882 工艺 ——后缀自动机 最小表示法
- bzoj 2882: 工艺 后缀自动机
- 后缀自动机总结
- 【BZOJ 3277】串 广义后缀自动机
- 【后缀自动机】hihocoder1441 后缀自动机一·基本概念
- [SPOJ1812]LCS2 - Longest Common Substring II-后缀自动机
- bzoj 4566: [Haoi2016]找相同字符 后缀自动机
- 后缀自动机(SAM)
- spoj7258 Lexicographical Substring Search(SUBLEX),后缀自动机
- 后缀自动机求第k大字符串 SPOJ - SUBLEX
- Hdu 5343 MZL's Circle Zhou 后缀自动机
- 【bzoj2555】SubString 后缀自动机+LCT
- ●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)