最长的共同前缀

时间:2012-06-17 06:49:16

标签: algorithm suffix-array

假设我构造了一个后缀数组,即一个整数数组,以字典顺序给出字符串所有后缀的起始位置。

示例:对于字符串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)的长度其他后缀最有效的方式是什么?

1 个答案:

答案 0 :(得分:4)

根据您的评论,我假设我们可以访问后缀数组SA以及标准LCP数组,即在索引i> 0时告诉我们的数据结构,后缀SA[i]及其词典前身SA[i-1]的最长公共前缀的长度是多少。

我将使用字母L来指代我们想要构建的特殊LCP数组,如问题中所述。我将使用字母N来表示输入字符串str的长度。

然后我们能做的就是:

  1. 确定后缀数组中str的位置。我们可以通过线性筛选SA来找到条目0。 (说明:str是从位置0开始的str的后缀。因此,0必须显示为后缀数组的条目。)

  2. 假设我们找到的条目位于索引k处。然后我们可以设置L[k]:=N,因为SA[k]是字符串本身,并且具有与其自身共同的N个字符的前缀。

  3. 然后我们可以设置L[k-1]:=LCP[k]L[k+1]:=LCP[k+1],因为这就是标准LCP的定义方式。

  4. 然后我们从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]的前缀和输入字符串strL[i]必须是这两者中的最小值,因为L[i]表示前缀SA[i]str的共同点,并且不能超过其前缀{与SA[i+1]相同,否则它在后缀数组中的位置将更接近k。

  5. 我们也从i:= k + 2到N向前计数并设置

    L[i] := min(LCP[i],L[i-1])
    

    基于相同的推理。

  6. 然后设置L的所有N个值,并且它花费的时间不超过O(N)时间,假设对数组的随机访问和整数比较分别为O(1)。

    由于我们计算的数组长度为N个条目,因此O(N)的复杂度是最佳的。

    (注意:您可以分别在k-1和k + 1处开始步骤4和5中的循环,并摆脱步骤3.额外的步骤仅用于解释 - 希望 - - 更容易理解。)