动态规划8:最优编辑str1-->str2
2017-07-19 08:35
253 查看
题目:
对于两个字符串A和B,我们需要进行插入、删除和修改操作将A串变为B串,定义c0,c1,c2分别为三种操作的代价,求出将A串变为B串所需要的最少代价。给定两个字符串A和B,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价。保证两串长度均小于等于300,且三种代价值均小于等于100。
样例:"abc",3,"adc",3,5,3,100返回:8
思路:
将问题拆分成为2个维度的问题(A串作为纵向,B串作为横向),建立二维数组来进行解决。在建立二维数组时要注意是建立n*m的矩阵还是建立(n+1)*(m+1)的矩阵,关键是思考对于数组为””空串的情形是否要作为初始条件,即是否应该让空串作为初始条件,从实际意义上来理解,空串也是一种字符串,且与可能要求将空串编辑成为某个字符串,或者将某个字符串编辑成为空串,因此需要对字符串A,B从空串“”开始进行拆分考虑。但是实际上是否从空串或者0开始分解要看如果分解成为这种初始条件是否可以据此求出后面的所有情况的结果,即所求的第1行,第1列应当是有效的,能够据此求出后面的一系列情况,而不是固定的记住。
这个题目和找零钱问题类似。
dp[n+1]
d457
[m+1] 其中dp[i][j]表示s1[0...i-1]转变成s2[0...j]的代价
插入删除修改代价分别为 ic dc rc
初始情况:
(1)dp[0][0]表示s1 s2都是空串,所以代价为0
(2)dp[0][j]第一行,表示s1是空串,转变成s2[j],那么代价就是插入j个字符的代价dp[0][j]=ic*j
(3)dp[i][0]第一列,表示s2是空串,那么转换代价就是删除s1中的i个字符代价 dp[i][0]=dc*i;
递归:
d[i][j]来自以下四种情况:最小值
(1)s1[0...i-1]能够转换成s2[0...j],此时代价为转换代价+删除一个字符的代价。即d[i][j]=d[i-1][j]+dc
(2)s1[0...i]能够转换成s2[0...j-1],此时代价为转换代价+插入一个字符的代价。即d[i][j]=d[i][j-1]+ic
(3)当s1[i]!=s[j]时,d[i][j]=d[i-1][j-1]+rc
(4)当s1[i]==s[j]时,d[i][j]=d[i-1][j-1]
public class MinCost {
public int findMinCost(String s1, int n, String s2, int m, int c0, int c1, int c2) {//插入删除修改依次为c0 c1 c2
// write code here
if(s1==null&&s2==null) return 0;
int[][] dp=new int[n+1][m+1];
//初始条件
dp[0][0]=0;//表示两个空串的转换
for(int i=1;i<=m;i++){//空串转换成s2=插入i个字符的代价
dp[0][i]=i*c0;
}
for(int i=1;i<=n;i++){//字符串转成空串=删除i个字符的代价
dp[i][0]=i*c1;
}
//递归
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=Math.min( (dp[i-1][j]+c1), (dp[i][j-1]+c0) );
if(s1.charAt(i-1)==s2.charAt(j-1)){
dp[i][j]=Math.min( dp[i][j], dp[i-1][j-1]);
}else{
dp[i][j]=Math.min(dp[i][j], dp[i-1][j-1]+c2);
}
}
}
return dp
[m];
}
}
对于两个字符串A和B,我们需要进行插入、删除和修改操作将A串变为B串,定义c0,c1,c2分别为三种操作的代价,求出将A串变为B串所需要的最少代价。给定两个字符串A和B,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价。保证两串长度均小于等于300,且三种代价值均小于等于100。
样例:"abc",3,"adc",3,5,3,100返回:8
思路:
将问题拆分成为2个维度的问题(A串作为纵向,B串作为横向),建立二维数组来进行解决。在建立二维数组时要注意是建立n*m的矩阵还是建立(n+1)*(m+1)的矩阵,关键是思考对于数组为””空串的情形是否要作为初始条件,即是否应该让空串作为初始条件,从实际意义上来理解,空串也是一种字符串,且与可能要求将空串编辑成为某个字符串,或者将某个字符串编辑成为空串,因此需要对字符串A,B从空串“”开始进行拆分考虑。但是实际上是否从空串或者0开始分解要看如果分解成为这种初始条件是否可以据此求出后面的所有情况的结果,即所求的第1行,第1列应当是有效的,能够据此求出后面的一系列情况,而不是固定的记住。
这个题目和找零钱问题类似。
dp[n+1]
d457
[m+1] 其中dp[i][j]表示s1[0...i-1]转变成s2[0...j]的代价
插入删除修改代价分别为 ic dc rc
初始情况:
(1)dp[0][0]表示s1 s2都是空串,所以代价为0
(2)dp[0][j]第一行,表示s1是空串,转变成s2[j],那么代价就是插入j个字符的代价dp[0][j]=ic*j
(3)dp[i][0]第一列,表示s2是空串,那么转换代价就是删除s1中的i个字符代价 dp[i][0]=dc*i;
递归:
d[i][j]来自以下四种情况:最小值
(1)s1[0...i-1]能够转换成s2[0...j],此时代价为转换代价+删除一个字符的代价。即d[i][j]=d[i-1][j]+dc
(2)s1[0...i]能够转换成s2[0...j-1],此时代价为转换代价+插入一个字符的代价。即d[i][j]=d[i][j-1]+ic
(3)当s1[i]!=s[j]时,d[i][j]=d[i-1][j-1]+rc
(4)当s1[i]==s[j]时,d[i][j]=d[i-1][j-1]
public class MinCost {
public int findMinCost(String s1, int n, String s2, int m, int c0, int c1, int c2) {//插入删除修改依次为c0 c1 c2
// write code here
if(s1==null&&s2==null) return 0;
int[][] dp=new int[n+1][m+1];
//初始条件
dp[0][0]=0;//表示两个空串的转换
for(int i=1;i<=m;i++){//空串转换成s2=插入i个字符的代价
dp[0][i]=i*c0;
}
for(int i=1;i<=n;i++){//字符串转成空串=删除i个字符的代价
dp[i][0]=i*c1;
}
//递归
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=Math.min( (dp[i-1][j]+c1), (dp[i][j-1]+c0) );
if(s1.charAt(i-1)==s2.charAt(j-1)){
dp[i][j]=Math.min( dp[i][j], dp[i-1][j-1]);
}else{
dp[i][j]=Math.min(dp[i][j], dp[i-1][j-1]+c2);
}
}
}
return dp
[m];
}
}
相关文章推荐
- 动态规划-最优编辑
- 动态规划---->最优二分检索树
- 动态规划---->最优二分检索树
- 动态规划方法生成最优二叉查找树
- 集合上的动态规划---最优配对问题(推荐:*****)
- 动态规划---->货郎担问题
- 动态规划之最优二叉搜索树
- 最优配对问题(集合上的动态规划) —— 状压DP
- 集合上的动态规划---最优配对问题(推荐:*****) // uva 10911
- 动态规划之编辑距离问题
- 小白进阶之动态规划-最优二叉搜索树
- 动态规划 字符串编辑距离
- 动态规划---->0/1背包问题
- 动态规划4-最优二叉查找树
- 动态规划之-用局部最优和全局最优实现时间优化
- 动态规划-编辑距离问题
- 基于动态规划的矩阵连乘最优方法
- 集合上的动态规划---最优配对问题(推荐:*****) // uva 10911
- 动态规划之编辑距离问题
- 集合上的动态规划---最优配对问题(推荐:*****)