Algorithm 在两个大数组中使用哪种算法获得最长字符串匹配?

Algorithm 在两个大数组中使用哪种算法获得最长字符串匹配?,algorithm,Algorithm,这个问题很容易解释:我们有两个大数组(32位整数值),我们必须找到给定数量的连续位置(n)以上的所有公共序列 例如,如果n=3,则要比较的数组为: a = [1, 3, 5, 7, 3, 2, 7, 4, 6, 7, 2, 1, 0, 4, 6] b = [2, 5, 7, 3, 2, 3, 4, 5, 6, 3, 2, 7, 4, 6, 0] 算法H应返回两个数组: r0 = [5, 7, 3, 2] r1 = [3, 2, 7, 4, 6] (或者更好,它与第一个数组的相对位置和匹配的连

这个问题很容易解释:我们有两个大数组(32位整数值),我们必须找到给定数量的连续位置(n)以上的所有公共序列

例如,如果n=3,则要比较的数组为:

a = [1, 3, 5, 7, 3, 2, 7, 4, 6, 7, 2, 1, 0, 4, 6]
b = [2, 5, 7, 3, 2, 3, 4, 5, 6, 3, 2, 7, 4, 6, 0]
算法H应返回两个数组:

r0 = [5, 7, 3, 2]
r1 = [3, 2, 7, 4, 6]
(或者更好,它与第一个数组的相对位置和匹配的连续字节数)


我认为一个很好的起点是n,但也许有人知道一种更适合我的问题的算法。

如果我理解正确,n是序列的最小大小,
然后我将使用Boyer Moor搜索算法的一个变体()

我认为使用后缀树查找LCS的算法非常适合。以相同的方式构建后缀树,但在最后阶段,您不会寻找两个字符串都有子体的最深节点。您正在查找深度超过
n
且两个字符串都有子体的所有节点。

我认为您引用的wikipedia页面上的算法几乎完全符合您的要求。您只需要修改它们,以将所有答案保持在一定的大小上,而不是只保留最长的答案。例如,该页面上的动态规划解决方案可以修改如下:

function LCSubstr(S[1..m], T[1..n], min_size)
    L := array(1..m, 1..n)
    ret := {}
    for i := 1..m
        for j := 1..n
            if S[i] = T[j]
                if i = 1 or j = 1
                    L[i,j] := 1
                else
                    L[i,j] := L[i-1,j-1] + 1
                if L[i,j] >= min_size
                    ret := ret ∪ {S[i-z+1..z]}
    return

如前所述,这将包括前缀和最长匹配项。通过跟踪在L中找到的字符串,并在我们发现返回集有扩展名时从返回集中删除前缀,可以过滤掉这些字符串。

我相信这是一个开放的研究问题,通常在匹配/对齐DNA序列的背景下研究。研究人们是如何使用DNA的,或者找到一些可用的库,你可能会有更好的运气。@Mark:这是一个开放的研究问题吗?但BM算法不适用于字符串搜索?我的问题是找到两个大字符串之间的所有子字符串。字符串本质上是一个域中的数字序列,所以它基本上不重要。您可以简单地将子字符串设置为搜索每个可能的数组大小/n序列(从位置i到i+n,从i+1到i+1+n…),然后执行BM。(如果存在一个更大的相同序列,您将找到初始的n大小的序列,并且可以简单地继续测试一个更大的后缀)我知道,所以您可以通过搜索每个子字符串(大小为n)来使用它从第二个数组中的第一个数组开始,在这种情况下使用后缀树或trie可能更好,因为从基字符串生成每个子字符串是一个n^2操作。再加上一个最佳案例BM,你看到的是mn^2,最好是+1,但我要强调的是,如果m和n都很大,你真的需要O(m+n)广义后缀树解决方案,而不是O(mn)DP解决方案,正如OP所说的那样。