最小编辑代价
最小编辑代价
题目:最小编辑代价
《程序员代码面试指南》第68题 P230 难度:校★★★☆
同样分为经典动态规划和经典动态规划结合空间压缩两种方法。
经典动态规划方法:
同样建立二维动态规划表,大小为(M+1)×(N+1)的矩阵dp,dp[i][j]的值代表str1[0..i-1]编辑成str2[0..j-1]的最小代价。
dp矩阵每个位置的值计算如下(具体原理见书P231):
- dp[0][0]=0
- 第一列dp[i][0]=dc*i
- 第一行dp[0][j]=ic*j
- 其它位置dp[i][j],取以下四种可能的值中的最小值:
- dc+dp[i-1][j]
- dp[i][j-1]+ic
- 如果str1[i-1]!=str2[j-1],dp[i-1][j-1]+rc
- 如果str1[i-1]==str2[j-1],dp[i-1][j-1]
public int minCost1(String str1, String str2, int ic, int dc, int rc) {
if (str1 == null || str2 == null) {
return 0;
}
char[] chs1 = str1.toCharArray();
char[] chs2 = str2.toCharArray();
int row = chs1.length + 1;
int col = chs2.length + 1;
int[][] dp = new int[row][col];
for (int i = 1; i < row; i++) {
dp[i][0] = dc * i;
}
for (int j = 1; j < col; j++) {
dp[0][j] = ic * j;
}
for (int i = 1; i < row; i++) {
for (int j = 1; j < col; j++) {
if (chs1[i - 1] == chs2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = dp[i - 1][j - 1] + rc;
}
dp[i][j] = Math.min(dp[i][j], dp[i][j - 1] + ic);
dp[i][j] = Math.min(dp[i][j], dp[i - 1][j] + dc);
}
}
return dp[row - 1][col - 1];
}
经典动态规划结合空间压缩方法:
与“矩阵的最小路径和”问题不同,本题dp[i][j]依赖dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]。还需要一个变量来保存dp[j-1]没更新之前的值,即dp[i-1][j-1]。
此外,选择str1和str2中长度较短的一个作为列对应的字符串,长度较长的一个作为行对应的字符串。如果str1做了列对应的字符串,把插入代价ic和删除代价dc交换一下即可。
public int minCost2(String str1, String str2, int ic, int dc, int rc) {
if (str1 == null || str2 == null) {
return 0;
}
char[] chs1 = str1.toCharArray();
char[] chs2 = str2.toCharArray();
char[] longs = chs1.length >= chs2.length ? chs1 : chs2;
char[] shorts = chs1.length < chs2.length ? chs1 : chs2;
if (chs1.length < chs2.length) { // str2较长就交换ic和dc的值
int tmp = ic;
ic = dc;
dc = tmp;
}
int[] dp = new int[shorts.length + 1];
for (int i = 1; i <= shorts.length; i++) {
dp[i] = ic * i;
}
for (int i = 1; i <= longs.length; i++) {
int pre = dp[0]; // pre代表左上角的值ֵ
dp[0] = dc * i;
for (int j = 1; j <= shorts.length; j++) {
int tmp = dp[j]; // dp[j]没更新前先保存下来
if (longs[i - 1] == shorts[j - 1]) {
dp[j] = pre;
} else {
dp[j] = pre + rc;
}
dp[j] = Math.min(dp[j], dp[j - 1] + ic);
dp[j] = Math.min(dp[j], tmp + dc);
pre = tmp; // pre变成dp[j]没更新前的值
}
}
return dp[shorts.length];
}

浙公网安备 33010602011771号