如何解决具有动态编程和二维数组的 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"))
然而,我的代码最终输出的是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 举报,一经查实,本站将立刻删除。