我有两个字符串,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个不匹配)。谁有更好的方法来更有效地解决这个问题?
答案 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-
如果你保证只有一个问题的解决方案,我认为赛义德是对的,你必须使用动态编程来解决它