同一问题的递归与动态规划解法
2016-10-03 14:39
381 查看
问题:
给定一个源串和目标串,能够对串进行入戏操作:
1、在给定的位置上插入一个字符;
2、替换任意字符;
3、删除任意字符;
写一个程序,返回最小的操作数,使得进行这些操作后源串等于目标串,假设源串和目标串的长度都小于2000;
例如:
修改一个字符(如把“a”替换为“b”);
增加一个字符串(如把“abdd”变为“aebdd”);
删除一个字符串(如把“travelling”变为“traveling”);
现在给定源字符串"abcdefg"和目标“abcdef”,那么从源目标转换为目标字符串只需要以此删除操作,所以,最小操作数为1;
解析:
利用递归的方式,我们首先要考虑如何能够将问题从一个大问题转化为一个规模相同的小问题。如果两个字符串A=xabcdae和B=xfdfa,他们的第一个字符相同,则只要计算A[2,...7]=abcdae和B[2,...5]=fdfa的距离就可以了。但如果两个字符不相同,那么就要分别进行讨论,
1、删除A串的第一个字符,然后计算A[2,...lenA】和B[1,...lenB]的距离;
2、删除B串的第一个字符,然后计算A[1,...lenA]和B[2,...lenB]的距离;
3、修改A串的第一个字符为B串的第一个字符,然后计算A[2,...lenA]和B[2,...lenB]的距离;
4、修改B串的第一个字符为A串的第一个字符,然后计算A[2,...lenA]和B[2,...lenB]的距离;
5、增加A串的第一个字符到B串的第一个字符之前,然后计算A[2,...lenA]和B[1,...lenB]的距离;
6、增加B串的第一个字符到A串的第一个字符之前,然后计算A[1,...lenA]和B[2,...lenB]的距离;
我么并不在乎如果当这两个字符串变的相等之后字符串是怎样的。所以,将上面6中情况合并为:
1、一步操作之后,再将A[2,...lenA]和B[1,...,lenB]变成相等字符串;
2、一步操作之后,再将A[2,...lenA]和B[2,...,lenB]变成相等字符串;
3、一步操作之后,再将A[1,...lenA]和B[2,...,lenB]变成相等字符串;
最终得到递归过程代码如下:
#include<iostream>
#include<string>
using namespace std;
int minValue(int t1, int t2, int t3)
{
int temp;
if (t1 >= t2){
temp = t2;
}
else{
temp = t1;
}
if (temp > t3){
temp = t3;
}
return temp;
}
int calculateStringDistance(string strA, int pABegin, int pAEend, string strB, int pBBegin, int pBEnd){
if (pABegin > pAEend){
if (pBBegin>pBEnd)
{
return 0;
}
else{
return pBEnd - pBBegin + 1;
}
}
if (pBBegin > pBEnd){
if (pABegin > pBEnd){
return 0;
}
else{
return pAEend - pABegin + 1;
}
}
if (strA[pABegin] == strB[pBBegin]){
return calculateStringDistance(strA, pABegin + 1, pAEend, strB, pBBegin + 1, pBEnd);
}
else{
int t1 = calculateStringDistance(strA, pABegin, pAEend, strB, pBBegin + 1, pBEnd);
int t2 = calculateStringDistance(strA, pABegin + 1, pAEend, strB, pBBegin, pBEnd);
int t3 = calculateStringDistance(strA, pABegin + 1, pAEend, strB, pBBegin + 1, pBEnd);
return minValue(t1, t2, t3) + 1;
}
}
int main(){
string A = "abcdefg";
string B = "abcdefgh";
cout << calculateStringDistance(A, 0, 6, B, 0, 7) << endl;
return 0;
}根据上面的递归过程,该问题明显符合动态规划的两个因素(最优子结构+重复子问题)使用动态规划的解法,首先给出递推公式:
设f[i,j]表示strA[i,lenA]与strB[j,lenB]的最小距离,则问题描述为:
根据递推公式,我们可以写出dp数组,如下:
我们假设字符数组A=“abcd”,字符数组B=“abcde”,那么:
右下角即为我们要求的最小值。程序如下:
#include<iostream>
#include<string>
using namespace std;
int minValue(int t1, int t2, int t3)
{
int temp;
if (t1 >= t2){
temp = t2;
}
else{
temp = t1;
}
if (temp > t3){
temp = t3;
}
return temp;
}
int calculateStringDistance(string strA, string strB){
int lenA = strA.length()+1;
int lenB =strB.length()+1;
int **dp = new int *[lenA];
for (int i = 0; i < lenA; i++){
dp[i] = new int[lenB];
}
for (int i = 0; i < lenA; i++){
dp[i][0] = i;
}
for (int j = 1; j < lenB; j++){
dp[0][j] = j;
}
for (int i = 1; i < lenA; i++){
for (int j = 1; j < lenB; j++){
if (strA[i] == strB[j]){
dp[i][j] = dp[i - 1][j - 1];
}
else{
dp[i][j] = minValue(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1;
}
}
}
int result = dp[lenA-1][lenB-1];
for (int i = 0; i < lenA; i++){
delete[]dp[i];
}
delete[]dp;
return result;
}
int main(){
string A = "abcdefg";
string B = "adefgh";
cout << calculateStringDistance(A,B) << endl;
return 0;
}
给定一个源串和目标串,能够对串进行入戏操作:
1、在给定的位置上插入一个字符;
2、替换任意字符;
3、删除任意字符;
写一个程序,返回最小的操作数,使得进行这些操作后源串等于目标串,假设源串和目标串的长度都小于2000;
例如:
修改一个字符(如把“a”替换为“b”);
增加一个字符串(如把“abdd”变为“aebdd”);
删除一个字符串(如把“travelling”变为“traveling”);
现在给定源字符串"abcdefg"和目标“abcdef”,那么从源目标转换为目标字符串只需要以此删除操作,所以,最小操作数为1;
解析:
利用递归的方式,我们首先要考虑如何能够将问题从一个大问题转化为一个规模相同的小问题。如果两个字符串A=xabcdae和B=xfdfa,他们的第一个字符相同,则只要计算A[2,...7]=abcdae和B[2,...5]=fdfa的距离就可以了。但如果两个字符不相同,那么就要分别进行讨论,
1、删除A串的第一个字符,然后计算A[2,...lenA】和B[1,...lenB]的距离;
2、删除B串的第一个字符,然后计算A[1,...lenA]和B[2,...lenB]的距离;
3、修改A串的第一个字符为B串的第一个字符,然后计算A[2,...lenA]和B[2,...lenB]的距离;
4、修改B串的第一个字符为A串的第一个字符,然后计算A[2,...lenA]和B[2,...lenB]的距离;
5、增加A串的第一个字符到B串的第一个字符之前,然后计算A[2,...lenA]和B[1,...lenB]的距离;
6、增加B串的第一个字符到A串的第一个字符之前,然后计算A[1,...lenA]和B[2,...lenB]的距离;
我么并不在乎如果当这两个字符串变的相等之后字符串是怎样的。所以,将上面6中情况合并为:
1、一步操作之后,再将A[2,...lenA]和B[1,...,lenB]变成相等字符串;
2、一步操作之后,再将A[2,...lenA]和B[2,...,lenB]变成相等字符串;
3、一步操作之后,再将A[1,...lenA]和B[2,...,lenB]变成相等字符串;
最终得到递归过程代码如下:
#include<iostream>
#include<string>
using namespace std;
int minValue(int t1, int t2, int t3)
{
int temp;
if (t1 >= t2){
temp = t2;
}
else{
temp = t1;
}
if (temp > t3){
temp = t3;
}
return temp;
}
int calculateStringDistance(string strA, int pABegin, int pAEend, string strB, int pBBegin, int pBEnd){
if (pABegin > pAEend){
if (pBBegin>pBEnd)
{
return 0;
}
else{
return pBEnd - pBBegin + 1;
}
}
if (pBBegin > pBEnd){
if (pABegin > pBEnd){
return 0;
}
else{
return pAEend - pABegin + 1;
}
}
if (strA[pABegin] == strB[pBBegin]){
return calculateStringDistance(strA, pABegin + 1, pAEend, strB, pBBegin + 1, pBEnd);
}
else{
int t1 = calculateStringDistance(strA, pABegin, pAEend, strB, pBBegin + 1, pBEnd);
int t2 = calculateStringDistance(strA, pABegin + 1, pAEend, strB, pBBegin, pBEnd);
int t3 = calculateStringDistance(strA, pABegin + 1, pAEend, strB, pBBegin + 1, pBEnd);
return minValue(t1, t2, t3) + 1;
}
}
int main(){
string A = "abcdefg";
string B = "abcdefgh";
cout << calculateStringDistance(A, 0, 6, B, 0, 7) << endl;
return 0;
}根据上面的递归过程,该问题明显符合动态规划的两个因素(最优子结构+重复子问题)使用动态规划的解法,首先给出递推公式:
设f[i,j]表示strA[i,lenA]与strB[j,lenB]的最小距离,则问题描述为:
根据递推公式,我们可以写出dp数组,如下:
我们假设字符数组A=“abcd”,字符数组B=“abcde”,那么:
右下角即为我们要求的最小值。程序如下:
#include<iostream>
#include<string>
using namespace std;
int minValue(int t1, int t2, int t3)
{
int temp;
if (t1 >= t2){
temp = t2;
}
else{
temp = t1;
}
if (temp > t3){
temp = t3;
}
return temp;
}
int calculateStringDistance(string strA, string strB){
int lenA = strA.length()+1;
int lenB =strB.length()+1;
int **dp = new int *[lenA];
for (int i = 0; i < lenA; i++){
dp[i] = new int[lenB];
}
for (int i = 0; i < lenA; i++){
dp[i][0] = i;
}
for (int j = 1; j < lenB; j++){
dp[0][j] = j;
}
for (int i = 1; i < lenA; i++){
for (int j = 1; j < lenB; j++){
if (strA[i] == strB[j]){
dp[i][j] = dp[i - 1][j - 1];
}
else{
dp[i][j] = minValue(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1;
}
}
}
int result = dp[lenA-1][lenB-1];
for (int i = 0; i < lenA; i++){
delete[]dp[i];
}
delete[]dp;
return result;
}
int main(){
string A = "abcdefg";
string B = "adefgh";
cout << calculateStringDistance(A,B) << endl;
return 0;
}
相关文章推荐
- 跳台阶问题 + 变态跳台阶问题 解法(动态规划递归 + 非递归)
- 01背包问题(当有的背包重量是非整数时)的递归(优化成动态规划+再用滚动数组优化)解法+一些动态规划(递归,搜索)的高级技巧
- 八皇后问题的高效解法-递归版
- 八皇后问题的高效解法-递归版(转)
- 递归--基于排列的八皇后问题解法
- 背包问题的递归和非递归的解法
- 整数划分问题---动态规划、递归
- 高效的八皇后问题非递归解法
- 04-07递归解法问题
- 整数划分问题解法2-动态规划
- C 递归问题的解法
- 格子取数问题的动态规划和递归解法之比较
- 蛙蛙推荐:统计最长不完全匹配子串频率的非递归解法(动态规划)
- n后问题迭代, 递归解法...
- 01背包问题 动态规划解法
- 整数划分问题解法2-动态规划
- 汉诺塔问题之递归解法
- 0-1背包问题及其动态规划求解之二——王晓东的书本解法
- 0-1背包问题的两种解法(回溯法和动态规划)
- 整数划分问题---动态规划、递归