日常菜的一天😕😕😕
题目链接------------------------------------>72. 编辑距离
这是一道动态规划问题,我们定义 d p [ i ] [ j ] dp[i][j] dp[i][j] 代表word1的前 i 个字符到word2的前 j 个字符的最少操作次数。
需要注意的是,对word1的增加一个字符和对word2删除一个字符是等价的,因为我们只关心操作次数,例如对于ho–>heo的转换,我们可以在h和o之间增加一个e,也可以在heo中删除e。虽然最终得到的word不一样,但是对于操作次数是一样的。
若我们已知abc---->bo的最小操作次数是x的话,那么:
1.abc—>bod的最小操作次数就是x+1,因为我们可以直接在abc后面增加d。(也可以将bod中的d删除,因为两种操作是等价的。)
2.abcd---->bo的最小操作次数就是x+1,因为我们可以直接把abcd中的d删除。
3.abcd---->bof的最小操作次数就是x+1,因为我们可以直接将abcd中的d替换成f。
我们将上述例子带入到定义的
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]中:
1.
d
p
[
3
]
[
3
]
=
d
p
[
3
]
[
2
]
+
1
dp[3][3] = dp[3][2] + 1
dp[3][3]=dp[3][2]+1
2.
d
p
[
4
]
[
2
]
=
d
p
[
3
]
[
2
]
+
1
dp[4][2] = dp[3][2] + 1
dp[4][2]=dp[3][2]+1
3.
d
p
[
4
]
[
3
]
=
d
p
[
3
]
[
2
]
+
1
dp[4][3] = dp[3][2] + 1
dp[4][3]=dp[3][2]+1
可以看出对于一个
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]来说它的值有三个来源:
d
p
[
i
]
[
j
−
1
]
+
1
,
d
p
[
i
−
1
]
[
j
]
+
1
,
d
p
[
i
−
1
]
[
j
−
1
]
+
1
dp[i][j-1] + 1,dp[i-1][j] + 1,dp[i-1][j-1] + 1
dp[i][j−1]+1,dp[i−1][j]+1,dp[i−1][j−1]+1。其中的最小值为
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]的值。
当然若word1中第i个字符和word2中第j个字符一样的话,我们并不需要上述过程,因为我们此时不需要任何操作,所以 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] dp[i][j] = dp[i-1][j-1] dp[i][j]=dp[i−1][j−1]
此时我们可得到状态转移方程:i 指向word1,j 指向word2
若word1[i] == word2[j],则
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
−
1
]
dp[i][j] = dp[i-1][j-1]
dp[i][j]=dp[i−1][j−1]
若word1[i] != word2[j],则
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
−
1
]
[
j
]
,
m
i
n
(
d
p
[
i
]
[
j
−
1
]
,
d
p
[
i
−
1
]
[
j
−
1
]
)
)
+
1
dp[i][j] = min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]))+1
dp[i][j]=min(dp[i−1][j],min(dp[i][j−1],dp[i−1][j−1]))+1
对于dp问题来说我们应当还有起始状态,起始状态就是我们可以直接确定的情况,显而易见就是有一个word为空串。
对于
d
p
[
0
]
[
j
]
dp[0][j]
dp[0][j]来说,
d
p
[
0
]
[
j
]
=
j
dp[0][j] = j
dp[0][j]=j。因为只需要往空串中增加字符即可。
对于
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]来说,
d
p
[
i
]
[
0
]
=
i
dp[i][0] = i
dp[i][0]=i。此时只需要把word1中的字符全部删除即可。
int minDistance(string word1, string word2) {
int len1 = word1.length(),len2 = word2.length();
int dp[len1+1][len2+1];
memset(dp,0,sizeof(dp));
for(int i = 0;i <= len1;i++)
dp[i][0] = i;
for(int j = 0;j <= len2;j++)
dp[0][j] = j;
for(int i = 1;i <= len1;i++)
{
for(int j = 1;j <= len2;j++)
{
if(word1[i-1] == word2[j-1])
dp[i][j] = dp[i-1][j-1];
else{
dp[i][j] = min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]))+1;
}
}
}
return dp[len1][len2];
}