字符串考前总结
复习字符串
- KMP
- AC自动机
- manacher
- SA
- SAM
AC自动机
Fail树
- 祖先是后代节点对应字符串的后缀
给模式串建AC自动机,文本串中模式串出现次数:走到的每个节点fail祖先单词结尾个数;模式串在文本串中出现次数:文本串走的时候cnt++,子树cnt和。
- 队列中就是拓扑序
DP
- 考虑一边生成字符串,一边在AC自动机上走,\(f[i][j]\)表示生成了i位(字符串前i位)自动机上走到j
- 考虑trie图上的转移 建出图来 矩乘/图的性质
题目
-
1212: [HNOI2004]L语言
f[i]表示\(S[1,i]\)是否能表示出来,走到每个节点用到祖先的单词结尾转移
-
3172: [Tjoi2013]单词
文本串就是模式串,插入时cnt++
-
套路DP
-
2434: [Noi2011]阿狸的打字机
结合题目的性质,一边模拟一边生成字符串,一个字符串结束后统一处理他的询问。fail树的dfs序。
-
添加新文本串,询问某个模式串在多少种文本串里出现过
模式串建AC自动机,考虑添加一个文本串,走到的节点记录下来求树链的并
后缀数组
sa是后缀排序后的结果
rnk是每个后缀的名次
height是第i名与第i-1名的LCP
如果只用到求LCP之类的直接写SA比写SAM方便一点吧
常用技巧
-
差分 注意长度变化
-
按Height大小把sa分组
-
枚举长度L,\(S_{1+i*L}\)设为关键点。每个长为L的子串覆盖且仅覆盖一个关键点,统计数量可以利用(最长延伸L-1)
-
两个字符串拼起来,用#隔开;自身反转拼起来
-
单调栈:称为最小值的区间 / 套个set,任意位置删除+二分查找
-
ST表
-
并查集:满足r-1成立时r也成立,枚举LCP长度,从大到小合并
题目
-
可重叠的k次最长重复子串
二分最长长度,sa分组同一组height>=mid
-
重复次数最多的连续重复子串
枚举L,计算每两个关键点向前向后能匹配多长
-
ABA(\(|B|\)已知)形式的子串有多少个
枚举\(|A|=L\),每个关键点i和i+B+L向前后匹配,最长L-1
-
LCS
直接上SAM / 拼起来,求height两个不在同一串的最大值
-
不重叠最长重复子串
二分+分组 / 并查集 , 核心都是看sa的最大差值
后缀自动机
Right集合
-
SAM中的一个状态s表示了一个Right−equivalence class,也就是所有Right集合=Right(s)的子串,长度[Min(s), Max(s)]
-
基数排序后递推,所有的np初始化为1(主链上的初始化为1) 同样可以递推最左/右位置
最后right=1的状态,出现位置就是Max(s)
Parent Tree
- Parent树祖先Right集合大,字符串长度(路径长度)短
- Parent祖先对应字符串集合是后代的后缀
- Max(fa)=Min(s)−1
- 反转字符串的后缀树,\(LCS \rightarrow LCP\)
性质
- 从init开始走转移边可以得到所有子串
- 出现向父亲(Parent边)传递,接收串数从儿子(仍然Parent边)获取
广义后缀自动机
- 把很多串的SAM建到了一个SAM上,建每个串的时候都从root开始(last=root)
- 广义后缀自动机是Trie树的后缀自动机,可以解决多主串问题
- 直接给Trie建GSAM,边dfs边建其他地方不变,会产生多余节点不过没关系
题目
-
最小循环表示 / 最小后缀(加一个最小的字符在最后)
-
LCS (注意走suffix link后更新当前长度t[u].val)
-
多个串LCS 每个的最大,多个的最小 注意向父亲传递,后代出现祖先一定可以取Max,拓扑逆序更新
-
字典序k小子串
-
LCT维护Parent-Tree
-
两个串统计CS个数 一定注意后代出现,父亲也出现了并且可以取最大
-
建出后缀树 树形DP
-
每个状态出现在不同子串的次数 GSAM 跑字符串,更新sl父亲,cur=当前串就停下
统计一个串出现次数,除了经过的状态,还要统计经过状态的Parent祖先!
-
和SA一样注意配合DP思想,不要总想直接做
-
周期同构:复制一遍贴在后面(最后一个字符可以不贴)
走的时候保证长度为n:这一步走完后Min(s)>=n时走par