【问题标题】:Is this Levenshtein Distance algorithm correct?这个 Levenshtein 距离算法是否正确?
【发布时间】:2023-03-23 22:32:02
【问题描述】:

我已经编写了下面的算法来计算 Levenshtein 距离,它似乎根据我的测试返回了正确的结果。时间复杂度为O(n+m),空间为O(1)。

我所看到的所有现有算法都具有 O(n*m) 的空间复杂度,因为它们创建了一个矩阵。我的算法有问题吗?

public static int ComputeLevenshteinDistance(string word1, string word2)
{
    var index1 = 0;
    var index2 = 0;
    var numDeletions = 0;
    var numInsertions = 0;
    var numSubs = 0;
    while (index1 < word1.Length || index2 < word2.Length)
    {
        if (index1 == word1.Length)
        {
            // Insert word2[index2]
            numInsertions++;
            index2++;
        }
        else if (index2 == word2.Length)
        {
            // Delete word1[index1]
            numDeletions++;
            index1++;
        }
        else if (word1[index1] == word2[index2])
        {
            // No change as word1[index1] == word2[index2]
            index1++;
            index2++;
        }
        else if (index1 < word1.Length - 1 && word1[index1 + 1] == word2[index2])
        {
            // Delete word1[index1]
            numDeletions++;
            index1++;
        }
        else if (index2 < word2.Length - 1 && word1[index1] == word2[index2 + 1])
        {
            // Insert word2[index2]
            numInsertions++;
            index2++;
        }
        else
        {
            // Substitute word1[index1] for word2[index2]
            numSubs++;
            index1++;
            index2++;
        }
    }

    return numDeletions + numInsertions + numSubs;
}

【问题讨论】:

  • 如果代码按预期工作,请考虑将其发布到codereview.stackexchange.com
  • 同意,这听起来像是代码审查的问题
  • 似乎给"avarice""vase" 提供了错误的结果... 应该是4(删除A,删除R,删除I,用S 代替C)但返回5。跨度>
  • 另一个测试用例:"crevasse""vase"。返回 8,应该是 4
  • 或者"strange""rangers",返回7应该是4。

标签: c# algorithm distance levenshtein-distance


【解决方案1】:

是评论,但我觉得它可能适合作为答案:

如果您想要任何给定输入的真正最短距离,简短的回答是“否”。

您的代码看起来更高效的原因(以及其他实现创建矩阵而不是执行您正在做的事情的原因)是您的逐步实现忽略了许多潜在的解决方案。

@BenVoigt 给出的示例说明了这一点,另一个可能更清晰的说明是 ("aaaardvark", "aardvark") 返回 8,应该是 2:它被绊倒了,因为它与第一个 a 匹配并认为它可以继续前进,而实际上是一个更优化的解决方案是考虑前两个字符的插入。

【讨论】:

  • 我没有调查过的有趣的旁注:("Aardvark", "aardvark") 返回 2 而不是 1(或 0)。如果您决定使用此例程,也许您可​​能会改进的一件事是在处理之前标准化大小写(或提供区分大小写的开关作为参数)
猜你喜欢
  • 2013-01-15
  • 1970-01-01
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-23
相关资源
最近更新 更多