題目描述
給定兩個字符串str1和str2,再給定三個整數ic,dc,rc,分別代表插入、刪除、替換一個字符的代價,返回將str1編輯成str2的最小代價。
舉例:
str1="abc" str2="adc" ic=5 dc=3 rc=2,從"abc"編輯到"adc"把b替換成d代價最小,爲2;
str1="abc" str2="adc" ic=5 dc=3 rc=10,從"abc"編輯到"adc",先刪除b再插入d代價最小,爲8;
分析
假設str1長度爲M[0.....M-1],str2長度爲N[0.......N-1],dp大小爲(M+1)*(N+1);
dp[i][j]表示str1[0......i-1]編輯成str2[0......j-1]的最小編輯代價,dp大小爲(M+1)*(N+1)是爲了從空串開始計算,即dp[0][0]表示空串編輯到空串的最小編輯代價。
如何生成dp[][]:
- dp[0][0]表示空串編輯成空串,故dp[0][0]=0;
- 求第一行dp[0][j],空串編輯成str2[0....j-1],則dp[0][j]=ic*j;
- 求第一列dp[i][0],str1[0......i-1]編輯成空串,則dp[i][0]=dc*i;
- 求dp[i][j],即str1[0....i-1]編輯成str2[0.....j-1],四種可能的途徑:
- str1[0....i-1]先編輯成str2[0.....j-2],再由str2[0.....j-2]到str2[0.....j-1],即dp[i][j-1]+ic;增
- str1[0....i-1]先編輯成str1[0.....i-2],再由str1[0.....i-2]到str2[0.....j-1],即dc+dp[i-1][j];刪
- 如果str1[i-1]==str2[j-1],則dp[i][j]=dp[i-1][j-1];啥都不用幹(cost=0)
- 如果str1[i-1]!=str2[j-1],則dp[i][j]=dp[i-1][j-1]+rc;改
總之dp[i][j]肯定是經過增、刪、改某一項操作後、或者啥都不用幹(cost=0)生成的
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Test;
/**
* Author: zxh
* Date: 2019/2/21 16:49
* Email:
* Desc:
*/
public class TestDynamicPlanTransferStringLeastCost {
private static final int aLen = 5;
private static final int bLen = 5;
private static final int insertCost = 5;
private static final int deleteCost = 6;
private static final int replaceCost = 7;
@Test
public void test() {
String source = RandomStringUtils.random(aLen, false, true);
String target = RandomStringUtils.random(bLen, false, true);
// String source = "123";
// String target = "124";
System.out.println("source字符串:" + source);
System.out.println("target字符串:" + target);
//dp[i][j]代表a前i個(0個,1個...不是index值)字符,調整到b前j個(0個,1個...不是index值)字符的最小代價
int[][] dp = new int[aLen + 1][bLen + 1];
//源字符串是空字符串時,不是index=0的元素時
for (int j = 0; j <= bLen; j++) {
dp[0][j] = j * insertCost;
}
//目標字符串是空字符串,不是index=0的元素時
for (int i = 0; i < aLen + 1; i++) {
dp[i][0] = i * deleteCost;
}
for (int i = 0; i < aLen; i++) {
for (int j = 0; j < bLen; j++) {
char charA = source.charAt(i);
char charB = target.charAt(j);
if (charA == charB) {
dp[i + 1][j + 1] = dp[i][j];
} else {
dp[i + 1][j + 1] = Math.min(Math.min(dp[i + 1][j] + insertCost, dp[i][j + 1] + deleteCost), dp[i][j] + replaceCost);
}
}
}
System.out.println("開始打印dp:");
for (int i = 0; i <= aLen; i++) {
for (int j = 0; j <= bLen; j++) {
System.out.print(dp[i][j] + ",");
}
System.out.println();
}
}
}
結果示例
source字符串:02118
target字符串:89406
開始打印dp:
0,5,10,15,20,25,
6,7,12,17,15,20,
12,13,14,19,21,22,
18,19,20,21,26,28,
24,25,26,27,28,33,
30,24,29,33,34,35,
Process finished with exit code 0