后缀自动机的应用

零.前置:

\(1.init:\)初始状态。数组

\(2.end:\)结束状态。数据结构

\(3.E:\)结束状态\(end\)集合。spa

\(4.fa(s):parent\)树上\(s\)的父亲节点。排序

\(5.Reg(s):\)节点\(s\)能达到的\(end\)的集合。字符串

\(6.mx(s):\)节点\(s\)所表明的子串的最长长度。it

\(7.mn(s):\)节点\(s\)所表明的字串的最短长度。class

\(8.Right(s):\)状态\(s\)出现的右端点集合。数据

\(9.ST(s):\)节点\(s\)能到达的状态集合(点数)。查询

一.后缀自动机的性质:

\(1.Right(s)\subset Right(fa(s))\)集合

\(2.mn(s) = mx(fa(s))+1\)

\(3.s\)所表明的全部串在母串中出现的次数和每次出现的右端点相同。

\(4.\)后缀自动机的\(parent\)树是原串的反向前缀树(把每一个前缀的反串插入到\(Trie\)树中,而且把没有分支的链合并)。

二.如何求拓扑序:

\(\exists e(u,v)\)\(mx(u) < mx(v)\);若\(fa(v)=u\)也能获得\(mx(u) < mx(v)\)。因此将节点按照\(mx\)数组排序,能够获得拓扑序(基排\(O(n)\))。

三.如何求Right(s):

若只求大小,能够按照逆拓扑序递推;若是还须要求具体节点,须要平衡树(启发式合并)/可持久化平衡树;若是须要动态维护\(|Reg(s)|\)(创建的同时维护),则须要一个数据结构,支持在有根树上加边删边,求子树和,由于有根把子树和转化成链上加减,单点查询而后\(LCT\)便可。

三.如何求ST(s):

逆拓扑序递推,若求本质不一样,则每一个状态贡献1;若相同算屡次,则每一个状态贡献\(|Right|\)次。

其余应用:

\(1.\)求本质不一样子串数量:\(\sum_{s}mx(s) - mn(s) + 1\)

\(2.\)求字符串的最小表示:先对\(S+S\)创建\(SAM\),而后在\(SAM\)上跑,每次贪心走字典序最小的出边,走\(|S|\)步便可。

\(3.\)求两个字符串的最长公共子串:对一个串创建\(SAM\),而后跑匹配,若是失配则跳\(fa\)

\(4.\)求后缀树和后缀数组:把反串建\(SAM\)而后\(parent\)树就是后缀树,后缀树上\(dfs\)获得后缀数组。

\(5.\)字典序\(k\)小子串:求\(ST\)而后相似线段树二分的去作。

\(6.\)求本质不一样的子串总长:\(\sum_{s}\sum_{i=mn(s)}^{mx(s)}i\)

\({\color{red}{\text{咕}}}{\color{green}{\text{咕}}}{\color{blue}{\text{咕}}}{\color{brown}{\text{咕}}}{\color{gold}{\text{咕}}}{\color{grey}{\text{咕}}}{\color{purple}{\text{咕}}}{\color{pink}{\text{咕}}}{\color{red}{\text{咕}}}{\color{green}{\text{咕}}}{\color{blue}{\text{咕}}}{\color{brown}{\text{咕}}}{\color{gold}{\text{咕}}}{\color{grey}{\text{咕}}}{\color{purple}{\text{咕}}}{\color{pink}{\text{咕}}}\)

相关文章
相关标签/搜索