72. 编辑距离(edit-distance)
给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
示例 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')
-
分析
这道题是一道难题,但也有所简化,将每个操作的权值变为了1,这样操作稍微简单, dp的逻辑是没变的.本题目是将word1(m)word2(n)构造成m+1*n+1的dp矩阵,dp[i][j] 表示将word1[0,i]编辑成word2[0,j]的最小代价,这里有一个选择, 即 dp[i-1][j]->dp[i][j],dp[i][j-1]->dp[i][j],dp[i-1][j-1]->dp[i][j] 最优子结构在这里选择,构造递推式:
d p [ i ] [ j ] = { j i = 0 i j = 0 m a x { d p [ i − 1 ] [ j ] + 1 , d p [ i ] [ j − 1 ] + 1 , { d p [ i − 1 ] [ j − 1 ] w o r d 1 [ i − 1 ] = = w o r d 2 [ j − 1 ] , d p [ i − 1 ] [ j − 1 ] + 1 w o r d 1 [ i − 1 ] ! = w o r d 2 [ j − 1 ] } } i > 0 , j > 0 dp[i][j]=\left\{ \begin{aligned} &j & i=0 \\ &i & j=0 \\ &max\{\\ &dp[i-1][j]+1,dp[i][j-1]+1,& \\ &\{\\ &dp[i-1][j-1] &word1[i-1]==word2[j-1] ,\\ & dp[i-1][j-1]+1 &word1[i-1]!=word2[j-1] \\ &\}\\ & \} & i>0,j>0 \\ \end{aligned} \right. dp[i][j]=⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧jimax{dp[i−1][j]+1,dp[i][j−1]+1,{dp[i−1][j−1]dp[i−1][j−1]+1}}i=0j=0word1[i−1]==word2[j−1],word1[i−1]!=word2[j−1]i>0,j>0
-
code
package main
import "fmt"
func minDistance(word1 string, word2 string) int {
//生成二维数组
dp:=make([][]int,1+len(word1))
for i:=0;i<=len(word1);i++{
dp[i]=make([]int,1+len(word2))
}
//init raw 0
for i:=1;i<=len(word2);i++{
dp[0][i]=dp[0][i-1]+1 //add
}
//init col 0
for i:=1;i<=len(word1);i++{
dp[i][0]=dp[i-1][0]+1 //del
}
for i:=1;i<=len(word1);i++{
for j:=1;j<=len(word2);j++{
min:=dp[i-1][j]+1 //del
max:=dp[i][j-1]+1 //add
if min>max{
min,max=max,min
}
if word1[i-1]==word2[j-1]{
dp[i][j]=dp[i-1][j-1]
}else{
//del then add
//replace
dp[i][j]=dp[i-1][j-1]+1
}
if min<dp[i][j]{
dp[i][j]=min
}
}
}
return dp[len(word1)][len(word2)]
}
func main(){
fmt.Println(minDistance("horse", "ros"))
//3
fmt.Println(minDistance("intention","execution"))
//5
}