最小编辑代价 动态规划
2017-12-10 21:30
211 查看
1、题目描述:来源于《算法与数据结构题目最优解》左程云著
给定两个字符串str1和str2,再给定三个整数ic、dc和rc,分别代表插入、删除和替换一个字符的代价,返回将str1编辑成str2的最小代价
2、输入
abc
adc
5 3 2
abc
adc
5 3 100
abc
abc
5 3 2
ab12cd3
abcdf
5 3 2
3、输出
2
8
0
8
4、题目解析
1)题目的关键还是在于找状态,这个题目的状态dp[i][j]就代表用str1的前 i 位 编辑成 str2 的前 j 位的最小代价。
2)关键点之二在于初始状态的时候,字符串的初始状态一般是空字符串,这样考虑起来就比较容易了,我一开始是从第一个字符开始的,其实也可以,不过不如空串直观。
3)关键点之三在于状态的迭代,这个的情况比较多,想从str1的前 i 个得到 str2的前 j 个,
a、可以是前 i-1 个组成了 前 j-1 个,这样就用str1第 i 个 替换成str2的第 j 个就行了,不过如果str1[i]==str2[j],
就不用替换了(我就没考虑到这种情况);
b、可以是前 i-1个组成了前 j 个,那么只需要删除第 i 个
c、可以是前 i 个组成了前 j-1 个,那么只需要再插入一个。
5、代码如下:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int getMin(int, int);
int main() {
string str1, str2;
int ic, dc, rc;//插入、删除、替换
int len1, len2;
int i, j;
getline(cin, str1);
getline(cin, str2);
cin >> ic >> dc >> rc;
len1 = str1.length();
len2 = str2.length();
vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1));//dp[i][j]代表用去str1的前i为变成str2的前j位的最小代价,并且初始化从空字符串开始
//下面对dp进行赋值,从dp[0][0]代表空字符串
dp[0][0] = 0;
for (i = 1; i < len1 + 1; ++i) {
dp[i][0] = dp[i - 1][0] + dc;
}
for (j = 1; j < len2 + 1; ++j) {
dp[0][j] = dp[0][j - 1] + ic;
}
for (i = 1; i < len1 + 1; ++i) {
for (j = 1; j < len2 + 1; ++j) {
if (str1[i] == str2[j])//一定要注意考虑str1[i]是否和str2[j]相等
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = dp[i - 1][j - 1] + rc;
dp[i][j] = getMin(dp[i][j],dp[i][j-1]+ic);
dp[i][j] = getMin(dp[i][j], dp[i - 1][j] + dc);
}
}
cout << "the minimum value is: " << dp[len1][len2] << endl;
}
int getMin(int v1, int v2) {
if (v2 < v1)return v2;
return v1;
}
给定两个字符串str1和str2,再给定三个整数ic、dc和rc,分别代表插入、删除和替换一个字符的代价,返回将str1编辑成str2的最小代价
2、输入
abc
adc
5 3 2
abc
adc
5 3 100
abc
abc
5 3 2
ab12cd3
abcdf
5 3 2
3、输出
2
8
0
8
4、题目解析
1)题目的关键还是在于找状态,这个题目的状态dp[i][j]就代表用str1的前 i 位 编辑成 str2 的前 j 位的最小代价。
2)关键点之二在于初始状态的时候,字符串的初始状态一般是空字符串,这样考虑起来就比较容易了,我一开始是从第一个字符开始的,其实也可以,不过不如空串直观。
3)关键点之三在于状态的迭代,这个的情况比较多,想从str1的前 i 个得到 str2的前 j 个,
a、可以是前 i-1 个组成了 前 j-1 个,这样就用str1第 i 个 替换成str2的第 j 个就行了,不过如果str1[i]==str2[j],
就不用替换了(我就没考虑到这种情况);
b、可以是前 i-1个组成了前 j 个,那么只需要删除第 i 个
c、可以是前 i 个组成了前 j-1 个,那么只需要再插入一个。
5、代码如下:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int getMin(int, int);
int main() {
string str1, str2;
int ic, dc, rc;//插入、删除、替换
int len1, len2;
int i, j;
getline(cin, str1);
getline(cin, str2);
cin >> ic >> dc >> rc;
len1 = str1.length();
len2 = str2.length();
vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1));//dp[i][j]代表用去str1的前i为变成str2的前j位的最小代价,并且初始化从空字符串开始
//下面对dp进行赋值,从dp[0][0]代表空字符串
dp[0][0] = 0;
for (i = 1; i < len1 + 1; ++i) {
dp[i][0] = dp[i - 1][0] + dc;
}
for (j = 1; j < len2 + 1; ++j) {
dp[0][j] = dp[0][j - 1] + ic;
}
for (i = 1; i < len1 + 1; ++i) {
for (j = 1; j < len2 + 1; ++j) {
if (str1[i] == str2[j])//一定要注意考虑str1[i]是否和str2[j]相等
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = dp[i - 1][j - 1] + rc;
dp[i][j] = getMin(dp[i][j],dp[i][j-1]+ic);
dp[i][j] = getMin(dp[i][j], dp[i - 1][j] + dc);
}
}
cout << "the minimum value is: " << dp[len1][len2] << endl;
}
int getMin(int v1, int v2) {
if (v2 < v1)return v2;
return v1;
}
相关文章推荐
- 最小编辑代价(动态规划)
- 动态规划系列问题-最小编辑代价
- 【动态规划】最小编辑代价
- 最小编辑代价(动态规划)
- 最小编辑代价---动态规划
- 最小编辑代价(动态规划)
- 递归与动态规划---最小编辑代价
- 左神算法 最小编辑代价
- 最小编辑代价
- 最小编辑代价
- 最小编辑代价
- 最小编辑代价&&华为OJ 编辑距离&&计算字符串的相似度
- 最小编辑代价
- Cheapest Palindrome - 最小代价构造回文 动态规划
- EditDistance,求两个字符串最小编辑距离,动态规划
- 最小编辑代价
- NuptOJ最小代价树——动态规划
- 最小编辑代价
- 动态规划——最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串最小编辑距离日记整理
- 【动态规划】字符串最小编辑距离Java实现