在后缀数组中使用二进制搜索查找所有实例

时间:2018-03-26 21:20:59

标签: python find-occurrences suffix-array

我想知道是否有一种实现的方法来获取给定子字符串和后缀数组的所有出现。我正在测试一个我在这里找到的函数:https://hg.python.org/cpython/file/2.7/Lib/bisect.py进行了一些修改。我得到的只是当有其他的时候出现的位置之一。例如,

seq = "ATGTGCAAGAATGAGGCAAG$" #original string
array = [20, 17, 6, 9, 18, 7, 13, 10, 0, 16, 5, 19, 8, 12, 15, 4, 14, 2, 11, 3, 1] #suffix array
def bisect_left(array, query, seq, lo=0, hi=None):
    if lo < 0:
        raise ValueError('must be non-negative')
    if hi is None: #by default len(array)
        hi = len(array)
    while lo < hi: 
        mid = (lo+hi)//2 #set the middle to binary search
        if seq[array[mid]:] < query:
            lo = mid+1
        else:
            hi = mid
    if not seq[array[lo]:array[lo]+len(query)] == query:
        raise IndexError('there is not any index for the query')
    return array[lo]
print(bisect_left(array, 'ATG', seq))

通过执行此操作,输出为10时应为0,10 可能有什么不对?

1 个答案:

答案 0 :(得分:0)

问题是你的搜索方法只返回一个匹配,当可能有几个匹配时。为了抓住所有这些,我可以想到两个选择:

  1. 首先找一场比赛。然后从该点上下移动后缀数组以查找任何其他匹配项。如果匹配的数量不是太大,那么这个解决方案应该足够了,但是如果有很多匹配则可能会很慢。
  2. 如果您期望大量匹配,更好的策略是执行两次二进制搜索。第一个二进制搜索应该在后缀数组中查找最左边的匹配,第二个搜索应该查找最右边的匹配。
  3. 下面我已经实现了第一个。我定义了一个帮助方法assuming that is a valid value in your scenario,只是为了避免大量丑陋的嵌套match_at

    []