后缀自动机的各种应用
检查字符串是否出现
给出一个文本串$T$和多个模式串$P$,检查$P$是否为$T$的一个子串
先给文本串$T$建立后缀自动机,然后沿根节点依次按照$P$的字符转移,如果在中途转移无法进行,则$P$不是$T$的子串,否则就是。
求本质不同子串个数
给出字符串$S$,求$S$的本质不同子串个数
给字符串$S$建立后缀自动机,后缀自动机上从根节点走到任意一个节点的路径都表示一个子串,又考虑到后缀自动机是DAG,所以可以进行DP
令$dp_i$为从$i$节点开始的路径数量(包括长度为0的路径),则有
$$dp_i=1+ \sum_{(i,j) \in E} dp_j$$
答案为$dp_1-1$,排除空子串
求不同子串总长度
给出字符串$S$,求$S$的本质不同子串总长度
借用求本质不同子串个数的式子,定义$f_i$表示从$i$点开始的子串总长度,由于$i$点由子节点转移来时还需要走一条边,就会增加子串个数个长度,则
$$f_i= \sum_{(i,j) \in E} f_j+dp_j$$
答案为$f_1$
字典序第K大子串
给出字符串$S$,再给定$K$,询问$S$中第$K$大的子串
给字符串$S$构建后缀自动机,求出每个点的不同子串个数,按字典序贪心走边
最小表示法
给出字符串$S$,求其最小表示法
给字符串$S+S$建立后缀自动机,$S$的所有表示法都为$S+S$长度为$|S|$的子串,按字典序贪心选取
求模式串出现次数
给出文本串$S$,再给出多个模式串$T$,求每个$T$在$S$中出现的次数
给字符串$S$建立后缀自动机,接下来求出后缀自动机上每个点的$endpos$集合大小,转移方程为
$$cnt_{link(v)}+=cnt_v$$
其中非复制来的点$cnt$初值为$1$,利用了$parent$树上子节点$endpos$并为该节点$endpos$集合的性质
在后缀自动机上寻找$T$,$cnt$值为出现次数
求模式串第一次出现的位置
给出文本串$S$,再给出多个模式串$T$,求每个$T$在$S$中第一次出现的位置
对于后缀自动机的每个状态维护其$endpos$中最小值,当一个节点新建时,$g_i=len_i-1$,当一个节点为复制而来时,$g_i=g_q$,$q$为其复制的样本
答案为$g_t-|T|+1$,$t$为$T$在后缀自动机上的状态
求模式串出现的所有位置
同上,求每个$T$在$S$中所有出现的位置
同上一题相似,维护$endpos$最小值,这次统计答案时需要找到所有后缀连接指向$t$的状态,这些状态的后缀都是$T$,在构建后缀自动机时维护每个状态是否为复制而来和所有后缀连接能够指向它的状态,遍历时跳过复制而来的节点,因为访问它的样本与访问它等效
答案为所有的$g-|T|+1$
最短的没有出现过的字符串
给定字符串$S$和一个字符集,求长度最短的没有出现过的字符串
在后缀自动机上DP
设$h_v$表示在$v$状态想使其无法转移最少需要添加的字符数,那么如果不存在字符集中某个字符的转移,$h_v=1$,否则$h_v=1+min h_w$
答案为$h_1$
两字符串最长公共子串
给定两字符串$S$和$T$,求其最长公共子串
对$S$构造后缀自动机,对于$T$中的每个位置,求到这个位置的最长公共子串。
设当前状态$v$,匹配的长度为$l$,$T$的下一位为$T_i$
- 如果存在$v$经由$T_i$的转移,$l$自增一,$v$转移
- 否则,$v=link(v)$,$l=len(v)$,如果仍然没有,循环执行,直至$v$回到根,此时$l=0$
答案为$l$在这一过程中的最大值
多字符串最长公共子串
给定$k$个字符串$S_i$,求其最长公共子串
同上,对于每一个状态维护数组存储不同的串在该位置的最长公共子串的最小值
答案为每一个状态的数组最大值