problem
Given two words word1 and word2, find the minimum number of steps
required to convert word1 to word2. (each operation is counted as 1
step.)You have the following 3 operations permitted on a word:
a) Insert a character b) Delete a character c) Replace a character
solution
只允许三种修改方式:
- 删除一个字符
- 插入一个字符
- 替换一个字符
问题1:
class Solution(object):
def minDistance(self, word1, word2):
m = len(word1)
n = len(word2)
arr = [[0]*(n+1) for _ in range(m+1)]
for i in range(m+1):
arr[i][0] = i
for i in range(n+1):
arr[0][i] = i
for i in range(1, m+1):
for j in range(1, n+1):
t = 0 if word1[i-1] == word2[j-1] else 1
arr[i][j] = min(arr[i-1][j-1]+t, arr[i-1][j]+1, arr[i][j-1]+1)
return arr[m][n]
问题2:
class Solution(object):
def minDistance(self, word1, word2):
m = len(word1)
n = len(word2)
arr = [[0]*(n+1) for _ in range(m+1)]
for i in range(m+1):
arr[i][0] = i
for i in range(n+1):
arr[0][i] = i
for i in range(1, m+1):
for j in range(1, n+1):
t = 0 if word1[i-1] == word2[j-1] else 2 #唯一的修改
arr[i][j] = min(arr[i-1][j-1]+t, arr[i-1][j]+1, arr[i][j-1]+1)
return arr[m][n]
总结
这个问题给我的思考在于它和最长公共子序列之间的关系,在这个问题中,允许插入、删除和替换。而在最长公共子序列中可以看做是只允许删除的编辑距离,不同的编辑方式只是在递推方程中有所区别而已,核心的方法只是当前两个字符串可以由哪两个字符串编辑而来。也就是知道如何写出递推方程。
另一个需要注意的地方就是要证明最优子结构性质,这个其实比较好理解,因为原问题编辑距离最小的时候,对应的编辑距离最短的子问题一定是最优的。
例如,对’abc’和’abb’之间的编辑距离来说,它们可以由:
- ‘ab’, ‘abb’
- ‘abc’, ‘ab’
- ‘ab’, ‘ab’(相当于其中一个替换最后一个字符 )
这三个子问题推出,原问题最优时一定对应子问题最优的时候,所以满足最优子结构性质。
因此,我们可以使用动态规划解法解决。