python 编辑距离_python – 最小编辑距离重建

我认为在这种情况下更深入地理解算法非常重要.我将向您介绍算法的基本步骤,而不是给您一些伪代码,并向您展示您想要的数据如何在最终矩阵中“编码”.当然,如果你不需要推出自己的算法,那么显然你应该只使用别人的,如

MattH suggests!

大图

这看起来像是Wagner-Fischer algorithm的实现.基本思想是计算“附近”前缀之间的距离,取最小值,然后计算当前字符串对的距离.例如,假设您有两个字符串’i’和’h’.让我们沿着矩阵的垂直和水平轴放置它们,如下所示:

_ h

_ 0 1

i 1 1

这里,’_’表示空字符串,矩阵中的每个单元对应于一个输入(”或’i’)到输出(”或’h’)的编辑序列.

从空字符串到任何长度为L的字符串的距离是L,(需要L个插入).从任何长度为L的字符串到空字符串的距离也是L(需要L个删除).这涵盖了第一行和第一列中的值,它们只是递增.

从那里,您可以通过从上,左和左上角值中取最小值并添加一个来计算任何位置的值,或者,如果字符串中该点处的字母相同,则取上面的值-left值不变.对于上表中(1,1)的值,最小值为0(0,0),因此(1,1)处的值为1,这是从“i”到“h”的最小编辑距离'(一个替代).因此,通常,最小编辑距离始终位于矩阵的右下角.

现在让我们做另一个,比较是喜.同样,矩阵中的每个单元对应于一个编辑序列,该编辑序列将输入(”,’i’或’is’)输入到输出(”,’h’或’hi’).

_ h i

_ 0 1 2

i 1 1 #

s 2 # #

我们首先扩展矩阵,使用#作为我们尚不知道的值的占位符,并通过递增来扩展第一行和第一列.完成后,我们可以开始计算标记为#above的位置的结果.让我们从(2,1)开始(在(行,列)中,即行主要表示法).在上,左上和左边的值中,最小值是1.表中相应的字母是不同的 – s和h – 所以我们将一个加到该最小值得到2,并继续.

_ h i

_ 0 1 2

i 1 1 #

s 2 2 #

让我们继续(1,2)的值.现在情况有所不同,因为表中相应的字母是相同的 – 它们都是我.这意味着我们可以选择在左上角的单元格中取值而不添加一个.这里的指导性直觉是我们不必增加计数,因为在这个位置上两个字符串都添加了相同的字母.而且由于两根琴弦的长度都增加了一倍,我们会对角线移动.

_ h i

_ 0 1 2

i 1 1 1

s 2 2 #

在最后一个空单元格中,事情会恢复正常.相应的字母是s和i,所以我们再次取最小值并加一,得到2:

_ h i

_ 0 1 2

i 1 1 1

s 2 2 2

这是我们得到的表格,如果我们继续这个过程的两个较长的单词,以is和hi-isnt(忽略标点符号)和提示开头:

_ h i n t

_ 0 1 2 3 4

i 1 1 1 2 3

s 2 2 2 2 3

n 3 3 3 2 3

t 4 4 4 3 2

这个矩阵稍微复杂一点,但这里的最终最小编辑距离仍然只有2,因为这两个字符串的最后两个字母是相同的.方便!

重新创建编辑序列

那么我们如何从这个表中提取编辑类型呢?关键是要认识到桌子上的移动对应于特定类型的编辑.因此,例如,从(0,0)到(0,1)的向右移动使我们从_ – > _,不需要编辑,_ – > h,需要一次编辑,一次插入.同样,从(0,0)到(1,0)的向下移动使我们从_ – > _,不需要编辑,i – > _,需要一次编辑,一次删除.最后,从(0,0)到(1,1)的对角线移动使我们从_ – > _,不需要编辑,i – > h,需要一次编辑,一次替换.

所以现在我们所要做的就是颠倒我们的步骤,从上,左和左上角的单元格中追溯局部最小值回到原点,(0,0),记住如果当前值与最小值,然后我们必须转到左上角的单元格,因为这是唯一一种不会增加编辑距离的运动.

以下是您可以采取的步骤的详细说明.从已完成矩阵的右下角开始,重复以下操作,直至到达左上角:

>查看左上角的相邻单元格.如果它不存在,请转到步骤3.如果单元格确实存在,请记下存储在那里的值.

>左上角单元格中的值是否等于当前单元格中的值?如果是,请执行以下操作:

>记录空操作(即等于).在这种情况下不需要编辑,因为此位置的字符是相同的.

>更新当前单元格,向上和向左移动.

>返回第1步.

>这里有很多分支:

>如果左侧没有单元格而上面没有单元格,则表示您位于左上角,算法已完成.

>如果左侧没有单元格,请转到步骤4.(这将继续循环,直到您到达左上角.)

>如果上面没有单元格,请转到步骤5.(这将继续循环,直到到达左上角.)

>否则,在左边的单元格,左上角的单元格和上面的单元格之间进行三向比较.选择价值最小的那个.如果有多个候选人,您可以随机选择一个;它们在这个阶段都是有效的. (它们对应于具有相同总编辑距离的不同编辑路径.)

>如果您选择了上面的单元格,请转到步骤4.

>如果您选择了左侧的单元格,请转到步骤5.

>如果您选择了左上方的单元格,请转到步骤6.

>你正在向上移动.请执行下列操作:

>在当前单元格中记录输入字符的删除.

>更新当前单元格,向上移动.

>返回第1步.

>你向左移动.请执行下列操作:

>在当前单元格中记录输出字符的插入.

>更新当前单元格,向左移动.

>返回第1步.

>你正在对角线移动.请执行下列操作:

>在当前单元格中记录输入字符的替换,以代替当前单元格的输出字符.

>更新当前单元格,向上和向左移动.

>返回第1步.

把它放在一起

在上面的示例中,有两种可能的路径:

(4, 4) -> (3, 3) -> (2, 2) -> (1, 2) -> (0, 1) -> (0, 0)

(4, 4) -> (3, 3) -> (2, 2) -> (1, 1) -> (0, 0)

扭转他们,我们得到

(0, 0) -> (0, 1) -> (1, 2) -> (2, 2) -> (3, 3) -> (4, 4)

(0, 0) -> (1, 1) -> (2, 2) -> (3, 3) -> (4, 4)

所以对于第一个版本,我们的第一个操作是向右移动,即插入.插入的字母是h,因为我们正在从isnt变为提示. (这对应于详细输出中的Insert,h.)我们的下一步操作是对角线移动,即替换或无操作.在这种情况下,它是无操作,因为两个位置的编辑距离相同(即字母相同).所以平等,我,我.然后向下移动,对应于删除.删除的字母是s,因为我们再次从isnt变为暗示. (通常,要插入的字母来自输出字符串,而要删除的字母来自输入字符串.)所以这是删除,s.然后是两个没有变化的对角线运动:Equal,n,n和Equal,t,t.

结果:

Insert, h

Equal, i, i

Delete, s

Equal, n, n

Equal, t, t

执行这些说明不是:

isnt (No change)

hisnt (Insertion)

hisnt (No change)

hint (Deletion)

hint (No change)

hint (No change)

总编辑距离为2.

我将把第二条最小路径作为练习.请记住,两条路径完全相同;它们可能不同,但它们将导致相同的最小编辑距离为2,因此完全可以互换.当您在矩阵中向后工作时,如果您看到两个不同的可能的局部最小值,您可以选择其中一个,并且最终结果保证是正确的

一旦你了解了这一切,根本不应该编码.在这种情况下,关键是要首先深入理解算法.一旦你完成了它,编码就很容易了.

积累与重建

最后,您可以选择在填充矩阵时累积编辑.在这种情况下,矩阵中的每个单元格都可以是元组:(2,”ins’,’eq’,’del’,’eq’,’eq’)).您将增加长度,并附加与最小先前状态的移动相对应的操作.这消除了回溯,因此降低了代码的复杂性;但它占用了额外的内存.如果执行此操作,最终编辑序列将与矩阵右下角的最终编辑距离一起显示.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值