假设我构造了一个后缀数组,即一个整数数组,以字典顺序给出字符串所有后缀的起始位置。
示例:对于字符串str=abcabbca
,
后缀数组是:
suffixArray[] = [7 3 0 4 5 1 6 2]
说明:
i Suffix LCP of str and str[i..] Length of LCP
7 a a 1
3 abbca ab 2
0 abcabbca abcabbca 8
4 bbca empty string 0
5 bca empty string 0
1 bcabbca empty string 0
6 ca empty string 0
2 cabbca empty string 0
现在构建了suffixArray
,我想在str
(字符串本身)和之间找到最长公共前缀(LCP)的长度其他后缀。 最有效的方式是什么?
答案 0 :(得分:4)
根据您的评论,我假设我们可以访问后缀数组SA
以及标准LCP
数组,即在索引i> 0时告诉我们的数据结构,后缀SA[i]
及其词典前身SA[i-1]
的最长公共前缀的长度是多少。
我将使用字母L来指代我们想要构建的特殊LCP数组,如问题中所述。我将使用字母N来表示输入字符串str
的长度。
然后我们能做的就是:
确定后缀数组中str
的位置。我们可以通过线性筛选SA
来找到条目0
。 (说明:str
是从位置0开始的str
的后缀。因此,0
必须显示为后缀数组的条目。)
假设我们找到的条目位于索引k处。然后我们可以设置L[k]:=N
,因为SA[k]
是字符串本身,并且具有与其自身共同的N个字符的前缀。
然后我们可以设置L[k-1]:=LCP[k]
和L[k+1]:=LCP[k+1]
,因为这就是标准LCP的定义方式。
然后我们从i:= k-2倒退到0并设置
L[i] := min(LCP[i+1],L[i+1])
这是有效的,因为在每次迭代中,LCP[i+1]
告诉我们相邻后缀SA[i]
和SA[i+1]
的最长公共前缀,而L[i+1]
告诉我们最长的公共前缀先前处理的后缀SA[i+1]
的前缀和输入字符串str
。 L[i]
必须是这两者中的最小值,因为L[i]
表示前缀SA[i]
与str
的共同点,并且不能超过其前缀{与SA[i+1]
相同,否则它在后缀数组中的位置将更接近k。
我们也从i:= k + 2到N向前计数并设置
L[i] := min(LCP[i],L[i-1])
基于相同的推理。
然后设置L
的所有N个值,并且它花费的时间不超过O(N)时间,假设对数组的随机访问和整数比较分别为O(1)。
由于我们计算的数组长度为N个条目,因此O(N)的复杂度是最佳的。
(注意:您可以分别在k-1和k + 1处开始步骤4和5中的循环,并摆脱步骤3.额外的步骤仅用于解释 - 希望 - - 更容易理解。)