字符串编辑距离(最小编辑次数)算法-解法推导

最近在研究一些算法,因为之前自己的编程都没有经过系统的学习,所以通过学一些算法和数据结构来提高编程水平。

关于字符串的编辑距离算法,网上的文章有很多,内容大同小异,都是用动态规划来做,而且给出了实现的代码。但是,对于算法中的状态转换方程 d[i, j] = min(d1,d2,d3) = min(d[i-1, j]+1,   d[i, j-1]+1,   d[i-1, j-1] + (A[i] == A[j] ? 0 : 1)) 的推导,说明都不太详细或者基于直觉,少有较为完整的证明。像知乎上就有人问(https://www.zhihu.com/question/23139644):

题主在理解状态转移方程的时候,一直过不去。
假设字符串A(长为n), B(长为m),0 < i <= n, 0 < j <= m,D(i, j)代表A[1:i]变为B[1:j]的编辑距离,编辑距离指由A=>B的最短操作数,每个操作都只针对一个字符。
那么 D(i,j) = min(D(i - 1, j - 1) + (A[i] == B[j]) ? 0 : 1, D(i - 1, j) + 1, D(i, j - 1) + 1)

如何用数学、严谨、形式化的方式去证明上述递推公式成立?而不是想当然、由题而知、显然可得?

下文以我自己的理解,结合图片,来推导状态转换方程。

问题描述

字符串的编辑距离是指,字符串A修改为字符串B所需要的最少的编辑次数。插入、删除、修改都算作一次修改。

解法推导

现在研究在老字符串到新字符串的编辑过程中,老字符串的 原有字符 的 变化 情况。可能的变化有:

  1. 被修改;
  2. 被删除;
  3. 位置移动(由插入新字符/删除字符导致)。

举个例子,例如从“abcdefg" -> “aebcdhf” 的一种编辑,原有字符的变化情况如下:

图中,“e”被修改,“g”被删除,“b” “c” “d” “e(后改为h)” “f” 的位置发生了变化。

值得注意的是,由于插入、修改和删除不涉及字符顺序的变化,所以原字符串中的字符的顺序在新字符串中不会发生变化。例如,若将 "ab" 修改为 “ba”,则视为两次修改: a 修改为 b,b 修改为 a,因为并没有规定“交换字符顺序”的编辑方式。

设源字符串为A,目标字符串为B;字符串 A 有 i 个字符;字符串 B 有 j 个字符。

现在考虑在某编辑中,对字符串 A 的 最后一个字符 A[i] 的处理情况。

情况有三种:

  1. 最后一个字符 被删除。此时的情况比较简单,只需要将字符串A剩下的字符串 A[0...i-1] 修改为字符串B即可(设最少编辑 k1次)。此时的最少编辑次数为 k1 + 1。
  2. 最后一个字符 未被删除,但是其在新字符串中 是最后一个字符。此时,需要将原字符串剩下的子串 A[1...i-1] 修改成为新字符串的子串 B[1...j-1](如下图所示)(设最少编辑 k2 次)。如果 A[i] == B[j], 则最后一个字符无需修改,最少编辑次数为 k2; 否则,需要修改最后一个字符,最少编辑次数为 k2 + 1。
  3. 最后一个字符 未被删除,但是其在新字符串中 不是最后一个字符。因为在编辑过程中,字符串的字符顺序不会变化,所以原字符串的前 i - 1 个字符在新字符串的位置必在 A[i] 的新位置之前(若未被删除)(如下图所示)。这样的编辑等价于将字符串 A 修改为字符串 B 的子串 B[1...j-1](设最少编辑 k3 次),然后再在尾部添加字符串 B 的最后一个字符即可。此时的最少编辑次数 k3 + 1。

 

由于这3种情况 涵盖了对最后一个字符的所有处理方式,所以,最少的编辑次数一定会从这三种情况中产生。设 d[i, j] 为字符串 A 的子串 A[1...i] 到 字符串B的子串 B[1...j] 的最短编辑距离,则:

  • 情况1: d1 = d[i-1, j] + 1;
  • 情况2: 当 A[i] = B[j] 时,d2 = d[i - 1, j - 1]; 否则,d2 = d[i - 1,  j - 1] + 1;
  • 情况3: d3 = d[i, j - 1] + 1。

因此,d[i, j] = min(d1,d2,d3) = min(d[i-1, j]+1,   d[i, j-1]+1,   d[i-1, j-1]+t) ,其中 t = 0(A[i] = B[j]),t = 1(A[i] != B[j])。

知道了状态转换方程,由动态规划来求解该问题的具体方法就不赘述了,需要注意的是初始条件的选取:

  • d[0, 0] = 0;
  • 当 i = 0 时,d[0, j] = j;(将空字符串修改为长度为 j 的字符串需要增添 j 次)
  • 当 j = 0 时,d[i, 0] = i。(将长度为 i 的字符串修改为空需要删除 i 次)

相关参考

https://www.zhihu.com/question/23139644/answer/98769510

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
字符串相似度算法是用来比较两个字符串之间的相似程度的算法。常用的字符串相似度计算方法有编辑距离算法、余弦相似度算法、Jaccard相似度算法等。其中,编辑距离算法是一种常用的字符串相似度计算方法,它通过计算两个字符串之间的最小编辑距离来衡量它们的相似程度。编辑距离指的是将一个字符串转换成另一个字符串所需的最少操作次数,包括插入、删除、替换三种操作。 编辑距离算法的实现可以采用动态规划的方法,具体步骤如下: 1. 初始化一个二维数组,数组的行数为第一个字符串的长度加1,列数为第二个字符串的长度加1。 2. 将第一行和第一列的值分别初始化为0到列数和0到行数。 3. 从第二行和第二列开始,遍历整个二维数组,计算每个位置的值。具体计算方法如下: - 如果第一个字符串的当前字符等于第二个字符串的当前字符,则该位置的值等于左上角位置的值。 - 否则,该位置的值等于左上角、左边、上边三个位置中的最小值加1。 4. 遍历完整个二维数组后,右下角的值即为两个字符串之间的最小编辑距离。 除了编辑距离算法,余弦相似度算法和Jaccard相似度算法也是常用的字符串相似度计算方法。余弦相似度算法通过计算两个向量之间的夹角余弦值来衡量它们的相似程度,适用于文本分类、信息检索等领域。Jaccard相似度算法则通过计算两个集合的交集与并集之间的比值来衡量它们的相似程度,适用于推荐系统、社交网络等领域。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

muddled

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值