72. Edit Distance 动态规划dp
2016-05-14 21:39
281 查看
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
Subscribe to see which companies asked this question
分析:
由于此题是dp问题的经典问题,因此决定翻译一份详尽的解析:
https://leetcode.com/discuss/43398/20ms-detailed-explained-c-solutions-o-n-space
此题是动态规划的经典问题。定义dp[i][j]表示将word1[0,,,i-1]转换为word2[0,,j-1]所需要的最少操作。状态转移方程有两种情况,边界问题以及一般情况。注意i,j都是从1开始。
边界条件:
很显然,将word1[0,,,i-1]转换为“”所需要至少i不操作。实际上,边界条件如下:
1、 dp[i][0]=i;
2、dp[0][j]=j;
下面我们将讨论一般情况,将一个非空word1[0,,i-1]转为另一个非空word2[0,,j-1]。下面我们将这个问题转为更小问题。假定我们知道如何将word1[0,,i-2]转换为word2[0,,j-2]至少需要dp[i-1][j-1],下面将考虑word1[i-1]与word2[j-1]。如果相等,不需要更多操作,因此dp[i][j]=dp[i-1][j-1]。如果不相等呢:
我们需要考虑三种情况;
1)将word1[i-1]转为word2[j-1](dp[i][j]=dp[i-1][j-1]+1);
2)删除word1[i-1],且 word1[0,,i-2]=word[0,,j-1] (dp[i][j]=dp[i-1][j]+1;
3)插入word2[j-1]如word1[0,,i-1]且word1[0,,i-1]+word2[j-1]=word2[0,,j-1](dp[i][j]=dp[i][j-1]+1)
需要注意到,删除我们将word1[0,,i-1]与word2[0,,j-1]问题转换为word[0,,i-2]与word2[0,,j-1],则为dp[i-1][j]+1;
对于插入,有相同的方法。
代码如下:
class Solution {
public:
int minDistance(string word1, string word2) {
if(word1.size()==0||word2.size()==0) return word1.size()?word1.size():word2.size();
unsigned m=word1.size();
unsigned n=word2.size();
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
for(int i=1;i<=m;++i) dp[i][0]=i;
for(int j=1;j<=n;++j) dp[0][j]=j;
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++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-1],min(dp[i-1][j],dp[i][j-1]))+1;
}
}
return dp[m]
;
}
};
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
Subscribe to see which companies asked this question
分析:
由于此题是dp问题的经典问题,因此决定翻译一份详尽的解析:
https://leetcode.com/discuss/43398/20ms-detailed-explained-c-solutions-o-n-space
此题是动态规划的经典问题。定义dp[i][j]表示将word1[0,,,i-1]转换为word2[0,,j-1]所需要的最少操作。状态转移方程有两种情况,边界问题以及一般情况。注意i,j都是从1开始。
边界条件:
很显然,将word1[0,,,i-1]转换为“”所需要至少i不操作。实际上,边界条件如下:
1、 dp[i][0]=i;
2、dp[0][j]=j;
下面我们将讨论一般情况,将一个非空word1[0,,i-1]转为另一个非空word2[0,,j-1]。下面我们将这个问题转为更小问题。假定我们知道如何将word1[0,,i-2]转换为word2[0,,j-2]至少需要dp[i-1][j-1],下面将考虑word1[i-1]与word2[j-1]。如果相等,不需要更多操作,因此dp[i][j]=dp[i-1][j-1]。如果不相等呢:
我们需要考虑三种情况;
1)将word1[i-1]转为word2[j-1](dp[i][j]=dp[i-1][j-1]+1);
2)删除word1[i-1],且 word1[0,,i-2]=word[0,,j-1] (dp[i][j]=dp[i-1][j]+1;
3)插入word2[j-1]如word1[0,,i-1]且word1[0,,i-1]+word2[j-1]=word2[0,,j-1](dp[i][j]=dp[i][j-1]+1)
需要注意到,删除我们将word1[0,,i-1]与word2[0,,j-1]问题转换为word[0,,i-2]与word2[0,,j-1],则为dp[i-1][j]+1;
对于插入,有相同的方法。
代码如下:
class Solution {
public:
int minDistance(string word1, string word2) {
if(word1.size()==0||word2.size()==0) return word1.size()?word1.size():word2.size();
unsigned m=word1.size();
unsigned n=word2.size();
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
for(int i=1;i<=m;++i) dp[i][0]=i;
for(int j=1;j<=n;++j) dp[0][j]=j;
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++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-1],min(dp[i-1][j],dp[i][j-1]))+1;
}
}
return dp[m]
;
}
};
相关文章推荐
- C++动态规划之最长公子序列实例
- C++动态规划之背包问题解决方法
- C#使用动态规划解决0-1背包问题实例分析
- 动态规划
- C++ 动态规划
- DP(动态规划) 解游轮费用问题
- 动态规划的用法——01背包问题
- 动态规划的用法——01背包问题
- 《收集苹果》 动态规划入门
- 《DNA比对》蓝桥杯复赛试题
- 《背包问题》 动态规划
- 自顶向下动态规划解决最长公共子序列(LCS)问题
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 关于爬楼梯的动态规划算法
- 动态规划 --- hdu 1003 **
- DP问题各种模型的状态转移方程
- 0-1背包解题过程
- 背包问题
- USACO 3.2.2:Stringsobits
- 字符串编辑距离