algorithm - 在另一个字符串中找到最大相似子串

标签 algorithm

我得到了两个字符串,n1 和 n2。除了这些,我还得到了一个数字 K。

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

一个例子应该很清楚:
n1 = 大不里士
n2 =都灵
K = 2
那么输出应该是:
我 = 2
j = 1
l = 4
[因为“briz”和“orin”有两个不同点]

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

最佳答案

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

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(n2)

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--
    }
}

关于algorithm - 在另一个字符串中找到最大相似子串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9339693/

相关文章:

c# - 这是快速排序吗?

c++ - MPI 遗传蒙特卡罗算法资源?

c# - 如何优化并使其更具可读性

algorithm - 游戏的战斗机制是如何运作的?

algorithm - Python(/C/Java) : How do I divide an integer by an integer, 并生成均匀分布的整数列表?

python - 在小于 O(n) 的时间内找到小于给定数字的斐波那契和

c++ - 使用O(1)辅助空间(LeetCode)从排序数组中删除重复项

c++ - 这2张魔法卡能发挥的最大技能是多少?

algorithm - (文本表示的)整数的任意基数转换算法

c++ - 用一个给定半径的圆覆盖最大点数的算法