后缀数组:
sa[i]:第i小的后缀的编号
rank[i]:编号为i的后缀的排名(从小到大)
heigt[i]:第i小的后缀和第I-1小的后缀的最长公共前缀
- 显然, s a [ r a n k [ i ] ] = r a n k [ s a [ i ] ] = i sa[rank[i]] = rank[sa[i]] = i sa[rank[i]]=rank[sa[i]]=i
后缀数组的构造
1、倍增:想要求出每个位置往后
2
k
2^k
2k个字符,这些字符的排名
由长度为
2
k
2^k
2k的排名可以得出长度为
2
k
+
1
2^{k+1}
2k+1的字串的排名
- 比较两个长为 2 k + 1 2^{k+1} 2k+1长的字串时,可以先比较前面一半(前 2 k 2^k 2k),在比较后面一半( 后 2 k 后2^k 后2k)
- 具体这里不再详细介绍‘’
基数排序:开权值范围个桶,把每个数放进桶里,求一遍前缀和,将每个数放进他应该存在的位置即可。
在后缀数组的构造中可以用基数排序来用
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的实践中完成对后缀数组的构造
第一遍按照第二关键字进行排序,以这个序列为与按顺序在按第一关键字进行排序
这个代码似乎有些复杂。。
然后就是求 h e i g h t 了 height了 height了
求这个东西十分复杂,似乎要用上ST表以及一堆结论来求。
这里不再(neng)详细介绍
Trie 上后缀数组
- 求后缀数组直接类比序列情形,倍增
一些例题
一、可重叠的最长重复子串
- 最长的height数组的值即为所求
二、不可重叠的最长重复子串
- 二分答案。再判定,是否存在两个长度为k的字串是相同的,且不重叠
三、可重叠至少出现k次的最长重复子串
- 同样是二分答案…
四、本质不同的子串个数
- ∑ k n − s a [ k ] + 1 − h e i g h t [ k ] \sum_k n-sa[k]+1-height[k] ∑kn−sa[k]+1−height[k]
五、最长回文子串
- 枚举回文中心,算正着和反着最长能匹配多少
六、连续重复字串
- 其实可以用KNP
七、重复次数最多的连续重复子串
- 枚举长度L,算长度为L的字串最多能连续出现几次
- 任何一个连续的长为L的字串,一定会跨过2*L其中的一个
- 重复多次会跨过两个
八、最长公共子串
- 相当于求某一个A的后缀和某一个B的后缀的最长公共前缀
九、不小于k个字符串中的最长子串
- 将n个字符串连起来,中间用字符隔开,求出后缀数组
十、每个字符串至少出现两次且不重叠的最长字串
- 将n个字符串连起来,中间用字符隔开,求出后缀数组
十一、出现或者反转出现在在每个字符串中的最大子串
- 讲了吗???
十二、长度不小于k的公共子串的个数
- 暴力:枚举A的一个后缀,枚举B的一个后缀,如果LCP>x,在答案加上max(x-k+1,0)