📅  最后修改于: 2023-12-03 15:36:38.777000             🧑  作者: Mango
后缀数组是一种数据结构,可以快速地处理字符串相关问题。在计算机科学中,后缀数组是字符串处理中的一个重要概念,它允许我们高效地执行子字符串匹配、排序和计数等操作。
后缀数组是由一个字符串的所有后缀按字典序排列而成的数组。假设有一个字符串 $S$,$S_i$ 表示字符串 $S$ 的第 $i$ 个字符,它的后缀数组为 $SA$,则有:
$$ S[SA[1]..n] \lt S[SA[2]..n] \lt \cdots \lt S[SA[n]..n] $$
其中 $n$ 为字符串 $S$ 的长度。
如字符串 $S$ 为 banana
时,其后缀数组为: [5, 3, 1, 0, 4, 2]
,即:
n a n a n a
5 a
3 n a
1 n a n a
0 b a n a n a
4 n
2 a n
后缀数组主要用于字符串匹配问题,它可以高效地解决许多与字符串有关的问题,例如子串生成、子串匹配、最长公共子串等等。
以计算字符串的子串数为例,可以通过后缀数组来高效地实现,时间复杂度为 $O(n\log n)$,其中 $n$ 为字符串的长度。
步骤如下:
代码如下(Python 3):
def count_substrings(s):
# 建立后缀数组
n = len(s)
SA = [i for i in range(n)]
SA.sort(key=lambda x: s[x:])
# 计算 LCP
height = [0] * n
h = 0
for i in range(n):
if h > 0:
h -= 1
if SA[i] == n - 1:
continue
j = SA[i] + 1
while j + h < n and i + h < n and s[j + h] == s[i + h]:
h += 1
height[i] = h
# 统计不同子串数
cnt = n - SA[0]
for i in range(1, n):
cnt += n - SA[i] - height[i - 1]
return cnt
参考文献: