【刷题之路】字符串的编辑距离
2016-06-07 11:24
197 查看
对于两个字符串A和B,我们需要进行插入、删除和修改操作将A串变为B串,定义c0,c1,c2分别为三种操作的代价,请设计一个高效算法,求出将A串变为B串所需要的最少代价。
给定两个字符串A和B,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价。保证两串长度均小于等于300,且三种代价值均小于等于100。
经典动态规划问题,简历一个二维数组来解决问题
首先确定初始状态,先建立一个m+1*n+1的二维数组,其中行数是B,列数是A,数组的左上角为A,B都为空字符串时,显然操作数为0,对于第一行,显然是当B为空时,不断扩大A时所需要的操作,显然需要不断删除A中元素来达到,所以第一行里的操作数为i*c1,同理对于第一列,A为空不断扩大B,则需要不断将B中字符插入A中,所以第一列的操作数为i*c0。初始状态设置完毕
对于数组中某一个res[i][j]来说,可能的状态一共有四种,
1、对于当前A来说,删除一个字符,然后将删除后的字符字符串再去变为当前B,而删去一个字符之后,变为B的最小操作数为res[i][j-1],即res[i][j]=res[i][j-1]+c1;
2、对于当前A来说,插入一个字符,然后将插入后的字符串再去变为当前B,插入一个字符后最小操作数,为res[i-1][j](注:这里需要理解,前两种操作的本质实际上是字符串对齐,也就是说让这之前的字符串全部相等,然后再去考虑后面的,例如这个插入操作,并不是res[i][j+1],因为我是要将A变为B,所以当插入一个字符后,应该将当前的A与上一个B的最小操作数返回,因为假如需要插入的话,必然是A短,加入了一个字符后应该基于没加入字符时的状态的B比较,也就是res[i-1][j])即res[i][j]=res[i-1][j]+c0;
3、对于当前A来说,替换一个字符,然后将替换后的字符串再去变为B,即res[i][j]=res[i-1][j-1]+c2,
4、对与当前A来说,如果与当前B字符相同,可以考虑不变化,即res[i][j]=res[i-1][j-1](3与4实际上是二选一,因为我们需要的是最小的操作数)
取四种操作数中最小的作为当前位置的值,代码如下
class MinCost {
public:
int findMinCost(string A, int n, string B, int m, int c0, int c1, int c2) {
// write code here
vector<int> sub(n+1);
vector<vector<int>> res(m+1,sub);
int i,j,temp1,temp2,temp3;
for(i=0;i<=n;i++){
res[0][i]=i*c1;
}
for(i=0;i<=m;i++){
res[i][0]=i*c0;
}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
temp1=res[i][j-1]+c1;
temp2=res[i-1][j]+c0;
if(A[j-1]==B[i-1]) temp3=res[i-1][j-1];
else temp3=res[i-1][j-1]+min(c2,c0+c1);
res[i][j]=min(temp1,min(temp2,temp3));
}
}
return res[m]
;
}
};
给定两个字符串A和B,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价。保证两串长度均小于等于300,且三种代价值均小于等于100。
经典动态规划问题,简历一个二维数组来解决问题
首先确定初始状态,先建立一个m+1*n+1的二维数组,其中行数是B,列数是A,数组的左上角为A,B都为空字符串时,显然操作数为0,对于第一行,显然是当B为空时,不断扩大A时所需要的操作,显然需要不断删除A中元素来达到,所以第一行里的操作数为i*c1,同理对于第一列,A为空不断扩大B,则需要不断将B中字符插入A中,所以第一列的操作数为i*c0。初始状态设置完毕
对于数组中某一个res[i][j]来说,可能的状态一共有四种,
1、对于当前A来说,删除一个字符,然后将删除后的字符字符串再去变为当前B,而删去一个字符之后,变为B的最小操作数为res[i][j-1],即res[i][j]=res[i][j-1]+c1;
2、对于当前A来说,插入一个字符,然后将插入后的字符串再去变为当前B,插入一个字符后最小操作数,为res[i-1][j](注:这里需要理解,前两种操作的本质实际上是字符串对齐,也就是说让这之前的字符串全部相等,然后再去考虑后面的,例如这个插入操作,并不是res[i][j+1],因为我是要将A变为B,所以当插入一个字符后,应该将当前的A与上一个B的最小操作数返回,因为假如需要插入的话,必然是A短,加入了一个字符后应该基于没加入字符时的状态的B比较,也就是res[i-1][j])即res[i][j]=res[i-1][j]+c0;
3、对于当前A来说,替换一个字符,然后将替换后的字符串再去变为B,即res[i][j]=res[i-1][j-1]+c2,
4、对与当前A来说,如果与当前B字符相同,可以考虑不变化,即res[i][j]=res[i-1][j-1](3与4实际上是二选一,因为我们需要的是最小的操作数)
取四种操作数中最小的作为当前位置的值,代码如下
class MinCost {
public:
int findMinCost(string A, int n, string B, int m, int c0, int c1, int c2) {
// write code here
vector<int> sub(n+1);
vector<vector<int>> res(m+1,sub);
int i,j,temp1,temp2,temp3;
for(i=0;i<=n;i++){
res[0][i]=i*c1;
}
for(i=0;i<=m;i++){
res[i][0]=i*c0;
}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
temp1=res[i][j-1]+c1;
temp2=res[i-1][j]+c0;
if(A[j-1]==B[i-1]) temp3=res[i-1][j-1];
else temp3=res[i-1][j-1]+min(c2,c0+c1);
res[i][j]=min(temp1,min(temp2,temp3));
}
}
return res[m]
;
}
};
相关文章推荐
- Lua中使用二维数组实例
- C++动态规划之最长公子序列实例
- C++动态规划之背包问题解决方法
- C#使用二维数组模拟斗地主
- C#二维数组基本用法实例
- javascript的日期对象、数组对象、二维数组使用说明
- PHP 如何获取二维数组中某个key的集合
- 改写函数实现PHP二维/三维数组转字符串
- java 二维数组矩阵乘法的实现方法
- Swift中定义二维数组的方法及遍历方法示例
- 举例理解C语言二维数组的指针指向问题
- C#和Java中二维数组区别分析
- C#使用动态规划解决0-1背包问题实例分析
- php去除二维数组的重复项方法
- php对二维数组进行相关操作(排序、转换、去空白等)
- php将一维数组转换为每3个连续值组成的二维数组
- php对二维数组按指定键值key排序示例代码
- PHP按指定键值对二维数组进行排序的方法
- PHP将二维数组某一个字段相同的数组合并起来的方法
- js二维数组定义和初始化的三种方法总结