带有动态规划和2D数组输出的Python编辑距离算法不是最优的

带有动态规划和2D数组输出的Python编辑距离算法不是最优的,python,algorithm,dynamic-programming,levenshtein-distance,edit-distance,Python,Algorithm,Dynamic Programming,Levenshtein Distance,Edit Distance,我遇到了编辑距离(Levenshtein距离)问题。我已经研究过其他类似的问题,并且确信我的问题与它们不同——无论是使用的语言还是方法 我使用了一个比较两个字符串的2D数组,以及动态编程来存储以前的值。如果字符串索引中的i和j匹配,它将输出0,因为我们不需要做任何事情;否则,输出为1。如下图所示,橙色箭头表示匹配 (以下代码根据答案中的建议进行编辑) 然而,在我的代码中,最终输出是8,而字符串“editing”和“distance”之间的最佳编辑距离应该是5,我非常困惑。你能从动态规划的角度来

我遇到了编辑距离(Levenshtein距离)问题。我已经研究过其他类似的问题,并且确信我的问题与它们不同——无论是使用的语言还是方法

我使用了一个比较两个字符串的2D数组,以及动态编程来存储以前的值。如果字符串索引中的i和j匹配,它将输出0,因为我们不需要做任何事情;否则,输出为1。如下图所示,橙色箭头表示匹配

(以下代码根据答案中的建议进行编辑)

然而,在我的代码中,最终输出是8,而字符串“editing”和“distance”之间的最佳编辑距离应该是5,我非常困惑。你能从动态规划的角度来帮助我吗?

你有两个错误

首先是初始化。您用0填充所有内容,但是当您要填充D[1][m]时,您可以查看上面的单元格(应该是m),然后找到一个0。确保正确填写边框

第二,你的迭代结束了。范围(1,n)超过“编辑”将为您提供“编辑”。要将N和M固定为1(
N=len(target)+1
),在比较中使用
target[i-1]==source[j-1]
,您有两个错误

首先是初始化。您用0填充所有内容,但是当您要填充D[1][m]时,您可以查看上面的单元格(应该是m),然后找到一个0。确保正确填写边框


第二,你的迭代结束了。范围(1,n)超过“编辑”将为您提供“编辑”。将它N和M固定为1(
N=len(target)+1
),在比较中使用
target[i-1]==source[j-1]
,啊,看起来我找到了一个解决方案,现在我必须回答我自己的问题。(我仍然对某些部分感到困惑,我回答这个问题只是简单介绍新的实现,以节省其他帮助者的时间)

因此,首先,我在原始代码中遗漏了一个条件,即,如果两个字符串输入中的一个为空怎么办?然后我们必须插入其他字符串中的所有内容。此后,最佳编辑距离就是另一个字符串的长度

    if i == 0:
        D[i][j] = j    
    elif j == 0:
        D[i][j] = i 
另外,关于代码的原始for循环,我从中学习了我的错误。如果我的理解是正确的,他们说如果两个指数(i和j)是一致的,我们所需要做的就是在图(i-1和j-1)上沿对角线向上移动,而不加任何计数

否则,如果指数不匹配,则我们会向i-1、j-1的方向移动,或者依赖于对角线向上移动。我在这一点上是正确的,除了在移动之后添加计数之外,而我在移动期间添加了计数

我仍然有点不确定它是如何工作的,但是我会比较下面的两种算法,如果有人能在评论中进一步解释,我将不胜感激

我的原始for循环(问题中存在)

下面是新的for循环,测试后输出正确:

        if target[i-1] == source[j-1]:
            D[i][j] = D[i-1][j-1]

        else:
            D[i][j] = 1 + min(D[i][j-1], D[i-1][j], D[i-1][j-1])
如果有人能进一步解释这是如何工作的,我将不胜感激,因为我对新代码的理解还只是肤浅的

最终代码:

def edit_distance(target, source):

    m = len(target)+1
    n = len(source)+1
    D = [[0 for x in range(n)] for x in range(m)]


    for i in range(m):
        for j in range(n):

            if i == 0:
                D[i][j] = j   
            elif j == 0:
                D[i][j] = i 

            elif target[i-1] == source[j-1]:
                D[i][j] = D[i-1][j-1]
            else:
                D[i][j] = 1 + min(D[i][j-1], D[i-1][j], D[i-1][j-1])    

    return D[m-1][n-1]

print(edit_distance("distance", "editing"))
# output = 5, which is correct

啊,看来我找到了一个解决办法,现在我必须回答我自己的问题。(我仍然对某些部分感到困惑,我回答这个问题只是简单介绍新的实现,以节省其他帮助者的时间)

因此,首先,我在原始代码中遗漏了一个条件,即,如果两个字符串输入中的一个为空怎么办?然后我们必须插入其他字符串中的所有内容。此后,最佳编辑距离就是另一个字符串的长度

    if i == 0:
        D[i][j] = j    
    elif j == 0:
        D[i][j] = i 
另外,关于代码的原始for循环,我从中学习了我的错误。如果我的理解是正确的,他们说如果两个指数(i和j)是一致的,我们所需要做的就是在图(i-1和j-1)上沿对角线向上移动,而不加任何计数

否则,如果指数不匹配,则我们会向i-1、j-1的方向移动,或者依赖于对角线向上移动。我在这一点上是正确的,除了在移动之后添加计数之外,而我在移动期间添加了计数

我仍然有点不确定它是如何工作的,但是我会比较下面的两种算法,如果有人能在评论中进一步解释,我将不胜感激

我的原始for循环(问题中存在)

下面是新的for循环,测试后输出正确:

        if target[i-1] == source[j-1]:
            D[i][j] = D[i-1][j-1]

        else:
            D[i][j] = 1 + min(D[i][j-1], D[i-1][j], D[i-1][j-1])
如果有人能进一步解释这是如何工作的,我将不胜感激,因为我对新代码的理解还只是肤浅的

最终代码:

def edit_distance(target, source):

    m = len(target)+1
    n = len(source)+1
    D = [[0 for x in range(n)] for x in range(m)]


    for i in range(m):
        for j in range(n):

            if i == 0:
                D[i][j] = j   
            elif j == 0:
                D[i][j] = i 

            elif target[i-1] == source[j-1]:
                D[i][j] = D[i-1][j-1]
            else:
                D[i][j] = 1 + min(D[i][j-1], D[i-1][j], D[i-1][j-1])    

    return D[m-1][n-1]

print(edit_distance("distance", "editing"))
# output = 5, which is correct

D=[[0]*m]*n
应替换为
D=[[0]*m表示范围内(n)]
D=[[0]*m]*n
应替换为
D=[[0]*m表示范围内(n)]
@cliff\u leaf它的
n=len(目标)+1
m=len 1
。您希望为边界行和列添加1(在图片中用0标记)。@cliff_leaf它是
n=len(目标)+1
m=len(源)+1
。您希望为边框行和列添加1(在图片中用0标记)。