后缀数组应用小结

前言

之前学了后缀数组,这真是一个神奇的东西。早就想总结一些SA的应用,但一直没时间,现在终于抽出空来写一下自己的心得。
本文只讨论后缀数组的一些应用,不一定全面,仅供参考
还不会后缀数组的同学请自学后再看本文,这里不再赘述后缀数组的基础实现
推荐一篇博客,里面对于基础的后缀数组总结的比较到位,YxuanwKeith大神的五分钟搞懂后缀数组!后缀数组解析以及应用
请不要吐槽标题,不知道你五分钟搞不搞得懂,反正我搞不懂 = = 。
下面进入正题。

后缀数组相关应用

单个字符串相关问题

比较常见的思路是先构造后缀数组,然后求Height数组,用这两个来求解。

重复子串问题

可重叠的最长重复子串问题

因为可重复,所以这类问题比较简单。只需要求 Height 数组的最大值。因为 Height[i] 表示排名为 i i1 的后缀的LCP,所以这个LCP一定是重复的,只需要求个最大值就是最长的。时间复杂度是线性的。

不可重叠的最长重复子串问题

有了不可重叠的限制稍微复杂一点,要用到 Height 数组的性质。先二分答案,将问题转化为判定性问题。假设我们二分的长度为 k ,那么答案的两个串它们在SA中的之间的 Height 值都会 k (想一想为什么?),所以我们把连续一段 Heightk 的后缀划分成一段,如果有某一段满足段中最大的SA值与最小值之差大于等于 k ,那么当前解就是可行的,因为满足这一条件的串一定不重叠。
注意:这种分段的思想在后缀数组相关问题中很常用

可重叠的 k 次最长重复子串

例:(JZOJ2265. 【Usaco DEC06 Gold】Milk Patterns)给定一个字符串,求至少出现 k 次的最长重复子串。
做法和上面的差不多,还是先二分,但是条件改变了,不是不重叠,而是出现至少 k 次。只需判断当前段内是否出现 k 个后缀即可。

子串计数问题

重复出现子串计数问题

例:(JZOJ1598. 文件修复)求一个字符串中有多少个至少出现两次的子串
这是比较简单的SA题,设每个后缀 Rank i ,其最多能贡献 Height[i]Height[i1] 个不同重复子串。
Ans=max(Height[i]Height[i1],0)

不相同子串计数问题

例:(spoj694,spoj705)给定一个字符串,求不相同的子串的个数。
和上面思路大相径庭。每个后缀 k 会产生 nSA[k]+1 个前缀,但是会重复计数,所以要减去前面相同的前缀,最后就是 nsa[k]+1height[k] 个子串。

字典序第K子串问题

例:(JZOJ2824. 【GDOI2012】字符串)给出一个字符串S,问该字符串的所有不同的子串中,按字典序排第K的字串。
应该勉强算计数问题吧。。。其实就是不相同子串个数的扩展,算出每个后缀贡献的不同子串个数,在二分找出最终子串位置(必然是某个后缀的前缀)。

连续重复子串问题

连续重复子串问题

例:给定一个字符串 L,已知这个字符串是由某个字符串 S 重复 R 次而得到的,
求 R 的最大值。
比较简单的重复子串问题。枚举串 S 长度 k ,如果 Rank[1] Rank[k+1] Height=|L|k 那么当前答案合法。

重复次数最多的连续重复子串问题

例:给定一个字符串 L ,求重复次数最多的连续重复子串。
还是枚举子串长度 k ,看这个长度对应每个位置(即 L[0],L[k],L[k2]... )之间的LCP是否等于 k 最长能扩到哪里,就是重复出现次数。

多个字符串相关问题

常用做法是将多个串连在一起,并且中间插入不同且没出现过的字符隔开(想一想为什么?)。但是这种题比较多变,不太好总结,只能简述一些例子。

一个字符串在所有字符串中出现次数问题

例:(JZOJ3258. 【TJOI2013】单词)给定 N 个字符串,求每个字符串在所有字符串中出现的次数。
对于当前字符串 S ,设其在总串中起始位置为 ST[i] ,那么我们在 Height 上二分区间 [ 1 , Rank[ST[i]] ] , [ Rank[ST[i]]+1 , n ] 内满足 Height|S| ,这之间的后缀数量就是答案。

字符串子串重复出现k次问题

例:(JZOJ3975. 串)给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身)
SA+线段树维护,详见题解。

其他相关问题

字符串不同种连续子串问题

例:(JZOJ4473. 生成魔咒)给定 n 个操作,每个操作在字符串 S 尾插入一个字符,求当前操作后共有多少不同种连续子串。
仔细分析,这题要减去前面的操作对当前影响(即重复的连续子串)。这个应该算是“前缀数组”吧。具体来说就是将字符串翻转后求一边SA,此时所得就是原串的前缀数组。然后在线段树维护一下。

后记

这篇博客是在复习之余码的,由于水平有限,难免有疏漏之处,欢迎批评和补充。后续(或许)会有例题及应用的补充。
参考资料:罗穗骞《后缀数组——处理字符串的有力工具》

以上.

你可能感兴趣的:(SA)