在另一个字符串中查找最大的类似子字符串

时间:2012-02-18 08:11:58

标签: algorithm

我有两个字符串,n1和n2。除此之外,我还获得了一个号码,K。

现在我需要找到三个数字 - 我,j,l这样:   从长度为l的n1中的索引i开始的子字符串与索引j为n2的长度为l的子字符串最多有K个不匹配。这是K不相似的最大子串。

一个例子应该说清楚:
n1 = tabriz
n2 = torino
K = 2
那么输出应该是:
i = 2
j = 1
l = 4
[因为“briz”和“orin”有两个不同]

当前方法:对于n1的每个子序列,我试图在n2中找到最大公共子序列(最多K个不匹配)。谁有更好的方法来更有效地解决这个问题?

3 个答案:

答案 0 :(得分:1)

这是一个简单的暴力。它计算每对可能的i和j对的长度。复杂度为O(n1.length * n2.length * min(n1.length,n2.length))。当两个字符串长度为n时,这是 O(n 3

for (i = 0; i < n1.length; i++)
{
    for (j = 0; j < n2.length; j++)
    {
        errors = 0
        len = 0

        while (errors <= k && i+len < n1.length && j+len < n2.length)
        {
             if (n1[i+len] != n2[j+len]) errors++
             if (errors <= k) len++
        }

        if (len > best) update best
    }
}


这是一个更有效的解决方案,它遍历i和j之间的所有可能的偏移,在该偏移处设置一个带有k个错误的子串,然后将子串移位(保持精确的k个错误)并观察每个点的长度。复杂度为O((n1.length + n2.length)* min(n1.length,n2.length))。当两个字符串长度为n时,这是 O(n 2

for (offset = -n1.length; offset < n2.length; offset++)
{
    // j is equal to (i + offset)

    start = (offset > 0) ? 0 : -offset
    stop = min(n1.length, n2.length - offset)

    errors = 0
    e = start // e is one past the end of the sequence, so l = e - i

    for (i = start; i < stop; i++)
    {
        // move the end of the substring to maintain exactly k errors
        while (e < stop && (errors < k || n1[e] == n2[e+offset]))
        {
            if (n1[e] != n2[e+offset]) errors++
            e++
        }

        if (e - i > best) update best

        if (n1[i] != n2[i+offset]) errors--
    }
}

答案 1 :(得分:0)

我认为你可以使用像LCS这样的动态编程来实现它,

common(i,j,l,k)= s1中的i处的最大子串strats,具有长度l,并且最多k个不匹配(对于所有i <= n,j <= n,l <= n,k&lt; ; = K) 首先你应该计算普通的(i,j,l,0),这是微不足道的。

表示k> 0:

  

对于所有1≤f≤k-1&amp;&amp; k-f≤t≤l-1:

     

如果str1 [i + l-t]!= str2 [j + l-t]

 common(i,j,l,k) = maximum{common(i,j,l-t-1,k-f) + common(i,j,t,f-1)} 
else
  common(i,j,l,k) = maximum{common(i,j,l-t,k-f) + common(i,j,t,f)} 

答案 2 :(得分:0)

保证有一个简单的解决方案吗?在这种情况下会发生什么:

N1 = qertyq

N 2 = quertac

K = 2

该算法将有多种解决方案 0,0,6

1,1,5-

2,2,4-

-3,3,3-

2,2,2-

如果你保证只有一个问题的解决方案,我认为赛义德是对的,你必须使用动态编程来解决它