微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

具有动态编程和二维数组的 Python 编辑距离算法 - 输出不是最佳的

如何解决具有动态编程和二维数组的 Python 编辑距离算法 - 输出不是最佳的

我遇到了编辑距离(Levenshtein distance)问题。我查看了其他类似的 stackoverflow 问题,并且确定我的问题与它们不同 - 无论是使用的语言还是方法

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

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

def edit_distance(source,target):
    n = len(target)+1
    m = len(source)+1

    # let D denote the 2-dimensional array,m is the column,n is row
    D = [ [0]*m for _ in range(n)] 

    # the loop inside is the target string,we operate this
    # while the loop outside is the source string

    for j in range(0,m):
        for i in range(0,n):
            if target[i-1] == source[j-1]:
                # match,insertion and deletion,find the path with least move
                D[i][j] = min(D[i-1][j-1],D[i-1][j]+1,D[i][j-1]+1)

            else:
                # mismatch,find the path with least move
                D[i][j] = min(D[i-1][j-1]+1,D[i][j-1]+1)
            
    return D[n-1][m-1]

print(edit_distance("distance","editing"))

enter image description here

然而,我的代码最终输出的是8,而字符串“editing”和“distance”之间的最佳编辑距离应该是5,我很困惑。能否请您从动态规划的方法中帮助它?

解决方法

你有两个错误。

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

其次,您的迭代已关闭。 range(1,n) over 'editing' 会给你 'diting'。要将 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 循环,我从 GeeksforGeeks 中学到了我的错误。如果我的理解是正确的,他们是说如果两个指数(i 和 j)一致,我们需要做的就是在图(i-1 和 j-1)上对角向上移动不添加任何计数。

否则,如果索引不匹配,我们要么向 i-1、j-1 的方向移动,要么依赖对角线向上移动。我是对的,除了计数是在移动后添加的,而我是在移动期间添加的。

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

我原来的 for 循环(出现在问题中)

for j in range(0,m):
    for i in range(0,n):
        if target[i-1] == source[j-1]:
            D[i][j] = min(D[i-1][j-1],D[i-1][j]+1,D[i][j-1]+1)

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

下面是新的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-1])    

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。