后缀数组基本知识

· · 个人记录

后缀数组

后缀数组是三个数组, 分别名为 sarankheight, 它们包含的信息都是同一个字符串的。

sa数组

sa 数组的定义 一个串 S 的后缀 S[l:|S|]l 表示, 将 S 的所有后缀排序, sa 数组存储的就是有序的后缀编号 l

暴力求 sa 如果用 C++ 带的 sort 函数来后缀排序的话, 时间复杂度是 O(n^2 \log_2 n) 的, 因为两个字符串的比较的时间复杂度是 O(n) 的。

快速排序与基数排序 对于用 k 个关键字排序 n 个数, 快速排序能做到 O(kn \log_2 n), 基数排序能做到 O(kn)。 下面简要分析一下它们的排序过程。

快速排序: 都知道 sort 函数提供了 cmp 函数的接口。 基数排序: 基数排序是将多个关键字分开, 从低优先级的关键字到高优先级的关键字依次排一遍(稳定排序)。

倍增法 倍增法的低复杂度依托于后缀排序这个问题的特殊性质。 有了 S[i\in[1,n], i+2^{k-1}-1] 的排序结果, 就可以得到 S[i\in[1,n], i+2^k-1] 的排序结果。 每一次倍增的过程中都要用到一次二关键字排序, 用基数排序就可以将一次倍增做到 O(n)。 倍增法的总复杂度为 O(n\log_2 n)

LCP 与 sa数组

lcp(i,j) 表示 LCP(sa_i, sa_j)

+

证明:对于两个串 $A$、 $B$, 它们都有 $n$ 个关键字(不足补空), $A_i$ 即 $A$ 的第 $i$ 关键字, $LCP(A,B) = k$ 即 $A$、 $B$ 的前 $k$ 个关键字都相等, 第 $k+1$ 关键字不同。 由于排序的性质, 对于一个串 $S$ 和与其相对位置相同的一些串来说, 排序后第一关键字与 $S$ 相同的那些串一定比第一关键字与 $S$ 不同的那些串近 (因为第一关键字相同的在整个数组中一定是连续的), 这也就说明了与 $S$ 的最长公共前缀为 $0$ 的串总是离 $S$ 较与 $S$ 的最长公共前缀为 $\ge 1$ 的串远。 在与 $S$ 的 $LCP$ 大于等于 $1$ 的那个连续段中, 第二关键字就是第一关键字, 用归纳法就可以发现这个 $\Delta \delta$ 性质。 **+** 有了这个 $\Delta \delta$ 性质, 可以证明一个定理: $$lcp(i,j) = min\{ lcp(i,k), lcp(k,j) \} \;\;\; (i\le k \le j)$$ 证明: 首先 $lcp(i,k) \ge min\{ lcp(i,k), lcp(k,j) \}$ 且 $lcp(k,j) \ge min\{ lcp(i,k), lcp(k,j) \}$, 由此推出 i、j 前 $min\{ lcp(i,k), lcp(k,j) \}$ 个字符相等, 即 $lcp(i,j) \ge min\{ lcp(i,k), lcp(k,j) \}$。 由 $\Delta \delta$ 性质, $lcp(i,j) \le lcp(i,k)$ 且 $lcp(j,i) \le lcp(j,k)$, 即 $lcp(i,j) \le min\{ lcp(i,k), lcp(k,j) \}$。 综上, $lcp(i,j) = min\{ lcp(i,k), lcp(k,j) \}$。 **需要注意的是, 这个定理也适用于任意字符串排序的结果数组, 而不仅仅是后缀排序的结果数组** 这个定理有一个应用: $$lcp(i,j) = \min_{k=i+1}^j\{lcp(k,k-1)\}$$ 证明: 将 $lcp(i,j)$ 按照定理展开, 最终就可以得到这个式子。(至于展开的过程中 $k$ 怎么选, 当然是随便选啦owo) --- ###**rk 数组** rk 数组是 sa 数组的反函数, 意即 $sa[rk[i]] = i$。 --- ###**height 数组** 定义 $$height_i = LCP(sa_i, sa_{i-1})$$ 意即排名为 i 的后缀与排名为 i-1 的后缀的 LCP。 又有 $$h_i = height_{rank_i} = LCP(i, sa_{rank_i - 1})$$ 意即后缀 i 与排在它前面一个的后缀的 LCP。 这里有一个定理: $$\forall 1<i \le n, \; h_i \ge h_{i-1} - 1$$ 证明: 如果 $h_{i-1} \le 1$, 那么显然成立。 如果 $h_{i-1} > 1$, 那么将 $i-1$ 和 $sa_{rank_{i-1} - 1}$ 都去掉第一个字符, 得到 $i$ 和 $sa_{rank_{i-1} - 1}+1$, 它们的 $LCP$ 就是 $h_{i-1}-1$; 由字典序的知识可知 $sa_{rank_{i-1} - 1}+1$ 依然排在 $i$ 前面, 再由 $i$ 前面离 $i$ 最近的是 $sa_{rank_i - 1}$ 和 $\Delta\delta$ 性质, 定理就得证了。 有了这个定理, 就可以 $O(n)$ 求出 $h$ 数组, 进而 $height$ 数组也就可以求出了。 以上就是后缀数组的基本知识了。