SAM
后缀自动机,就是一个能接受一个字符串所有后缀的自动机,本质是字典树。
考虑一个能接收一个字符串所有后缀的数据结构,显然字典树可以——只要把所有后缀加到字典树中,但是这样节点的个数是 O(N2) 的,接受不了,还有就是后缀树,但是后缀树的构造方法极其麻烦。这个时候后缀自动机就是很好的选择(事实上它也具备字典树和后缀树的性质)
构造
后缀自动机的构造不能说简单但是好记
可以看有具体证明的clj的课件:https://wenku.baidu.com/view/fa02d3fff111f18582d05a81.html
网上大佬的介绍(比较简单易懂):http://blog.sina.com.cn/s/blog_70811e1a01014dkz.html
还有一篇很具体的:http://e-maxx.ru/algo/suffix_automata
应用
个人把后缀自动机的应用分为两种:
1.利用其本质是字典树以及它的fail指针
因为本质是字典树切具有fail指针,那么就可以进行字符串匹配- 一个串u在另一个串v中的出现位置——对v建出后缀自动机,u在后缀自动机上跑,匹配不了就沿着fail指针继续匹配,找到终止位置x,x的right集合就是u在v中出现的位置的集合。
- 两个串的最长公共子串——一个串在在另一个串的后缀自动机上跑,能匹配则答案加一,不能就沿fail指针匹配,然后把答案设为当前节点的len。具体应用:http://blog.csdn.net/coldef/article/details/75127222(calc函数)
- 多个串的最长公共子串——对其中一个串建出后缀自动机,把另外所有串都放到上面跑一边,每个串求出在每个节点上的最长公共子串,每个节点取所有串在这个节点上答案的最小值,然后后缀自动机上每个节点的最大值就是答案,具体应用:SPOJ1812,BZOJ2946
- 最小表示法——建出后缀自动机,每次往最小的儿子跑
BZOJ2882 http://blog.csdn.net/coldef/article/details/54790695 - k小子串——建出后缀自动机,然后每个节点类似“26分”地跑:
bzoj3998 http://blog.csdn.net/coldef/article/details/54783495
……
2.利用它fail指针构成的parent树
- 主要是用来DP
还有一个性质,一个串的后缀自动机的parent树是反串的后缀树
根据这个性质,就可以求两个后缀的LCP(后缀树上的LCA)
bzoj3238 http://blog.csdn.net/coldef/article/details/54798928
- 主要是用来DP
3.还有就是可以用来构造后缀树组或后缀树(上面有说),然而我不会构造后缀树组…