给定两个单词 word1 和 word2,找到将 word1 转化为 word2 所需的最少操作步数。(这个步数称为两个单词的编辑距离)
对一个单词可以执行以下三种操作:
1、插入一个字符
2、删除一个字符
3、替换一个字符
示例:
Example 1:
Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation:
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')
Example 2:
Input: word1 = "intention", word2 = "execution"
Output: 5
Explanation:
intention -> inention (remove 't')
inention -> enention (replace 'i' with 'e')
enention -> exention (replace 'n' with 'x')
exention -> exection (replace 'n' with 'c')
exection -> execution (insert 'u')
我们要求的两个字符串的编辑距离,可以从两个字符串的子串的编辑距离得到。
设 D ( i , j ) D(i,j) D(i,j) 为 word1 前i个字符和 word2 前j个字符的编辑距离。
那么有递推关系式:
D ( i , j ) = m i n { D ( i − 1 , j ) + 1 D ( i , j − 1 ) + 1 D ( i − 1 , j − 1 ) + { 0 , w o r d 1 ( i ) = = w o r d 2 ( j ) 1 , e l s e D(i,j)=min\begin{cases} D(i-1,j) + 1\\ D(i,j-1) + 1\\ D(i-1,j-1) +\begin{cases} 0, &word1(i) == word2(j)\\ 1, &else \end{cases} \end{cases} D(i,j)=min⎩⎪⎪⎪⎨⎪⎪⎪⎧D(i−1,j)+1D(i,j−1)+1D(i−1,j−1)+{0,1,word1(i)==word2(j)else
我们要求的是 D ( m , n ) D(m,n) D(m,n),其中 m 和 n 分别为 word1 和 word2 的长度。
这样,最终会将 D 构成一个 m ∗ n m*n m∗n的二维矩阵,从左上角开始,从上到下从左到右开始遍历,最后到右下角为止。右下角的值即为所求。
注意:在遍历之前,需要先对矩阵进行初始化:
{ D ( i , 0 ) = i , i = 1 , . . . , m D ( 0 , j ) = j , j = 1 , . . . , n \begin{cases} D(i,0)=i,&i=1,...,m\\ D(0,j)=j,&j=1,...,n \end{cases} {D(i,0)=i,D(0,j)=j,i=1,...,mj=1,...,n
即:一个非空字符串和一个空字符串的编辑长度,就等于非空字符串的长度。
本算法时间复杂度为 O ( m n ) O(mn) O(mn)。
def minDistance(word1, word2):
"""
:type word1: str
:type word2: str
:rtype: int
动态规划。
"""
m = len(word1)
n = len(word2)
# 初始化,D(i,0)=i, D(0,j)=j
D = [[0] * (n+1) for _ in range(m+1)]
D[0] = [i for i in range(n+1)]
for i in range(m+1):
D[i][0] = i
# 迭代
for i in range(1,m+1):
for j in range(1,n+1):
tmp1 = min(D[i-1][j], D[i][j-1]) + 1
tmp2 = D[i-1][j-1] + (0 if word1[i-1] == word2[j-1] else 1)
D[i][j] = min(tmp1, tmp2)
return D[m][n]
if '__main__' == __name__:
word1 = "intention"
word2 = ""
print(minDistance(word1, word2))