后缀数组 - 总结
作者:互联网
构建过程
基数排序
tips:先比较低位,再比较高位
时间复杂度 o(nk) 其中 k 表示位数
思考:如果我把一个串的位数压缩的尽可能小 ???
倍增优化。考虑每一轮让比较的长度变为原来的两倍。
结构
一些应用
先引入两个新的数组:height[i] 表示 sa[i] 和 sa[i-1] 的最长公共前缀,即 lcp(sa[i-1],sa[i]);h[i] 表示 编号为i 的后缀与排在他前一位的后缀的最长公共前缀,即height[x[i]]。
那么 lcp(sa[i],sa[j]) 可以转化为 RMQ 问题。
知道 h[i] 很容易反推出 height[i] 的值。
一个结论: h[i]>=h[i-1]-1
这里砍掉首位留下来的 border 是很容易发现规律的。
可以线性计算 h 数组 ,复杂度证明使用势能分析。
- 求本质不同的子串个数
2333
- 求至少出现 k 次的子串最大长度
23333333
- 已知排名 k 求子串 (rnm)
例子:bzoj4310 跳蚤
233333333333333
- 多个字符串的问题
例子:spoj220
先将所有字符串连结起来,中间用 不相同的且没有出现在字符串中的 字符隔开(防止两个分隔符相互匹配,即 lcp(i,j) 一定合法),求后缀数组。
然后二分答案,再 将后缀分组 。我们只需要判断同一组后缀中是否每个给定的串都有两个子串不重叠地出现即可。
- 反直觉的 dp 题
例子:CF822E Liar
考察状态的设计和转移 (我的盲区 qwq …)
设 dp[i][j] 表示考虑 a 串中 1~i 的字符,已经选了 j 个子串,在 b 串中能覆盖到的 最大长度 。
这个状态设计只保留了能覆盖到的最大长度。看上去是反直觉的。
这样能够很方便地对 x[i] 和 x[cnt1+dp[i][j]+2] 求 lcp 从而完成转移
那么问题来了,为什么是 lcp ???
假设有一段没有匹配完。那么这一段没有匹配完的部分一定会在下一个子串中被匹配。那么我把这一段移到 s 的后面同样是满足条件的。
至此做到 o(1) 转移。
relax qwq…
标签:总结,子串,lcp,后缀,height,数组,sa,dp 来源: https://blog.csdn.net/cqbzlydd/article/details/122675794