最小编辑代价
题目描述:
给定两个字符串str1和str2,再给定三个整数ic,dc和rc,分别代表插入、删除和替换一个字符的代价,请输出将str1编辑成str2的最小代价: .
插入代价:ic ;删除代价:dc 替换代价:rc
算法分析:
1.动态规划:
dp[i][j]表示str1的前i个字符编辑成str2的前j个字符需要的最小操作代价
2.初始状态:
dp[i][0] = i,i次删除:即操作代价为i*dc;
dp[0][i] = i,i次插入:即操作代价为i*ic
3.过渡公式:
当i字符等于j字符时:dp[i][j] = dp[i-1][j-1],不需要额外操作
当i字符不等于j字符时:dp[i][j] = Math.min(insert, delete, replace)
其中:
int insert = dp[i][j-1] + 1; i个编辑成j-1个字符,再插入一个j
int delete = dp[i-1][j] + 1; i-1个编辑成j个字母,再删除一个i
int replace = dp[i-1][j-1] + 1; i-1个编辑成j-1个字母,再将i替换成j
填表
以:ic=5 dc=3 rc=2 为例
行为i, 列为j
填表规律:
当str[i]==str[j]: 直接为斜上角
当str[i]!=str[j]:
max (头上加ic, 左边加dc, 斜上角+rc)
str1 | a | b | c | d | e | f | ||
---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | ||
str2 | 0 | 0 | 3 | 6 | 9 | 12 | 15 | 18 |
a | 1 | 5 | 0 | 3 | 6 | |||
d | 2 | 10 | 5 | 2 | 7 | |||
c | 3 | 15 | 10 | 7 | 2 | |||
f | 4 | 20 | ||||||
d | 5 | 25 | ||||||
e | 6 | 30 |
str1[i] != str2[j]: dp[i][j] = max( dp[i][j-1]+ic , dp[i-1][j]+dc, dp[i-1][j-1]+rc )
dp[0][i] = i*ic
dp[j][0] = j*dc
str1[i] == str2[j]: dp[i][j] = dp[i-1][j-1]
dp[1][1] = dp[0][0] = 0
dp[2][1] = max( dp[2][0]+ic, dp[1][1]+dc, dp[1][0]+rc)
= max( 6+5, 0+3, 3+2) = 3
dp[3][1] = max( dp[3][0]+ic, dp[2][1]+dc, dp[2][0]+rc)
= max( 9+5, 3+3, 6+2) = 6
dp[1][2] = max( dp[1][1]+ic, dp[0][2]+dc, dp[0][1]+rc)
= max( 0+5, 10+3, 5+2) = 5
dp[2][2] = max( dp[2][1]+ic, dp[1][2]+dc, dp[1][1]+rc)
= max( 3+5, 5+3, 0+2) = 2
dp[3][2] = max( dp[3][1]+ic, dp[2][2]+dc, dp[2][1]+rc)
= max( 8+5, 4+3, 5+2) = 7
dp[1][3] = max( dp[1][2]+ic, dp[0][3]+dc, dp[0][2]+rc)
= max( 5+5, 15+3, 10+2) = 10
dp[2][3] = max( dp[2][2]+ic, dp[1][3]+dc, dp[1][2]+rc)
= max( 2+5, 10+3, 5+2) = 7
dp[3][3] = dp[2][2] = 2
填表规律:
当str[i]==str[j]: 直接为斜上角
当str[i]!=str[j]:
max (头上加ic, 左边加dc, 斜上角+rc)
代码:
class Solution {
public:
/**
* min edit cost
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @param ic int整型 insert cost
* @param dc int整型 delete cost
* @param rc int整型 replace cost
* @return int整型
*/
int minEditCost(string str1, string str2, int ic, int dc, int rc) {
// write code here
int l1 = str1.size();
int l2 = str2.size();
int dp[l1+1][l2+1];
//初始化dp[][]
for(int i=0; i<=l2; i++) dp[0][i] = ic*i; //carefully
for(int j=1; j<=l1; j++) dp[j][0] = dc*j;
for(int i=1; i<=l1; i++){
for(int j=1; j<=l2; j++){
if(str1[i-1] == str2[j-1]){
dp[i][j] = dp[i-1][j-1];
}
else{
dp[i][j] = min( min(dp[i][j-1]+ic,dp[i-1][j]+dc), dp[i-1][j-1]+rc );
}
}
}
return dp[l1][l2];
}
};