编辑距离(Edit Distance)

编辑距离是用于比较两个字符串或者符号序列之间距离的常用距离函数。

含义为:给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数,可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

用 leetcode 的题目来解释:

示例 1:

输入: word1 = “horse”, word2 = “ros”
输出: 3
解释:
horse -> rorse (将 'h’替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

示例 2:

输入: word1 = “intention”, word2 = “execution”
输出: 5
解释:
intention -> inention (删除 ‘t’)
inention -> enention (将 ‘i’ 替换为 ‘e’)
enention ->exention (将 ‘n’ 替换为 ‘x’)
exention -> exection (将 ‘n’ 替换为 ‘c’)
exection -> execution (插入 ‘u’)

动态规划计算编辑距离

动态规划的核心思想是用将原问题拆解成子问题

考虑:word1 = ‘ecf’,word2 = ‘abcd’

不放假设 word2 = ‘abcd’ 为固定模板,对 word1 = ‘ecf’ 进行编辑操作。

从后往前匹配(从前向后匹配也是可以的),先比较最后一个字符:‘f’ ≠ \neq =‘d’,那么就要对 word1 进行编辑,允许的编辑操作有三种:替换、插入、删除。

  1. 替换
    替换 f f f d d d,即 e c f → e c d ecf \rightarrow ecd ecfecd,接下来就比较 e c d ecd ecd a b c d abcd abcd 的编辑距离,则有:
    E D ( e c f , a b c d ) = E D ( e c d , a b c d ) + 1 = E D ( e c , a b c ) + 1 ED(ecf,abcd) = ED(ecd,abcd) + 1 = ED(ec,abc) + 1 ED(ecf,abcd)=ED(ecd,abcd)+1=ED(ec,abc)+1

  2. 插入
    在 word1 中插入 d d d,即 e c f → e c f d ecf \rightarrow ecfd ecfecfd,接下来就比较 e c f d ecfd ecfd a b c d abcd abcd 的编辑距离,则有:
    E D ( e c f , a b c d ) = E D ( e c f d , a b c d ) + 1 = E D ( e c f , a b c ) + 1 ED(ecf,abcd) = ED(ecfd,abcd) + 1 = ED(ecf,abc) + 1 ED(ecf,abcd)=ED(ecfd,abcd)+1=ED(ecf,abc)+1

  3. 删除
    删除 word1 中不匹配的字符 f f f,即 e c f → e c ecf \rightarrow ec ecfec,接下来就比较 e c ec ec a b c d abcd abcd 的编辑距离,则有:
    E D ( e c f , a b c d ) = E D ( e c , a b c d ) + 1 ED(ecf,abcd) = ED(ec,abcd) + 1 ED(ecf,abcd)=ED(ec,abcd)+1

综上所述,
E D ( e c f , a b c d ) = min ⁡ { E D ( e c , a b c ) , E D ( e c f , a b c ) , E D ( e c , a b c d ) } + 1 ED(ecf,abcd) = \min\{ ED(ec,abc) ,ED(ecf,abc), ED(ec,abcd) \}+ 1 ED(ecf,abcd)=min{ED(ec,abc),ED(ecf,abc),ED(ec,abcd)}+1

如果我们已知

  • E D ( e c f , a b c ) = 3 ED(ecf,abc) = 3 ED(ecf,abc)=3
  • E D ( e c , a b c d ) = 3 ED(ec,abcd) = 3 ED(ec,abcd)=3
  • E D ( e c , a b c ) = 2 ED(ec,abc) = 2 ED(ec,abc)=2

那么: E D ( e c f , a b c d ) = m i n ( 3 , 3 , 2 ) + 1 = 3 ED(ecf,abcd) = min(3,3,2) + 1 = 3 ED(ecf,abcd)=min(3,3,2)+1=3

可以看出,原问题拆解成了三个规模更小子问题,那么就可以使用动态规划来求解了!

def editDistance(word1: str, word2: str) -> int:
      n1 = len(word1)
       n2 = len(word2)
       dp = [[0] * (n2 + 1) for _ in range(n1 + 1)]
       
       # init
       for j in range(1, n2 + 1):
           dp[0][j] = j
       for i in range(1, n1 + 1):
           dp[i][0] = i
       
       for i in range(1, n1 + 1):
           for j in range(1, n2 + 1):
               if word1[i-1] == word2[j-1]:
                   dp[i][j] = dp[i-1][j-1]
               else:
                   dp[i][j] = min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1] ) + 1     
       return dp[-1][-1]

用一个 4 × 5 4\times 5 4×5 的数组 dp 来记录动态规划的过程:

  1. 初始化
  \, ‘’abcd
‘’01234
e1----
c2----
f3----
  1. 结果
  \, ‘’abcd
‘’01234
e11234
c22223
f33333
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值