动态规划----最长公共子序列问题
动态规划算法与分治法类似,其基本思想也是将待求解的问题分解为若干个子问题,先求解子问题,然后再从若干个子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划法求解的问题,经分解得到的子规模往往不是相互独立的。
动态规划算法适用于解最优化的问题。通常可以按照以下步骤设计动态规划算法:
- 找出最优解的性质,并刻画其结构特征
- 递归地定义最优值
- 以自底向上的方式计算出最优值
- 根据计算最优值时得到的信息,构造最优解
动态规划算法可有效解决最长公共子序列的问题。首先来看看最长公共子序列的定义:
这道题可以按照下面两种情况分析,解决动态规划问题最主要的是要用假设。
根据上面两种情况分析我们可以利用归纳法写出数学表达式:
因此根据数学表达式直接写出代码如下:
int lcsLength(char *X, char *Y, int m, int n)
{if (m == 0 || n == 0)return 0;else{if (X[m] == Y[n]) return lcsLength(X, Y,m - 1, n - 1) + 1;else{return max(lcsLength(X, Y, m, n - 1), lcsLength(X, Y, m - 1, n));}}
}
int main()
{char X[] = { "#ABCBDAB" };char Y[] = { "#BDCABA" };int mx = strlen(X) - 1;int ny = strlen(Y) - 1;int maxlen = lcsLength(X, Y, mx, ny);cout << maxlen << endl;
}
从运行结果我们可以看到确实计算出了X和Y的最长公共子序列的长度是4:
但是很明显这个程序重复计算了好多次相同规模的情况,因此我们用一个二维数组来标记,减少重复计算相同规模的子序列。
void PrintVector(vector<vector<int>>& c)
{for (int i = 0; i < c.size(); i++){for (int j = 0; j < c[i].size(); j++){cout << c[i][j] << " ";}cout << endl;}cout << endl;
}
int lcsLength(char *X, char *Y, int m, int n, vector<vector<int>>& c)
{if (m == 0 || n == 0)return 0;else if (c[m][n] > 0) return c[m][n];else{if (X[m] == Y[n]){c[m][n] = lcsLength(X, Y, m - 1, n - 1, c) + 1;}else{c[m][n] = max(lcsLength(X, Y, m, n - 1,c), lcsLength(X, Y, m - 1, n,c));}return c[m][n];}
}
int main()
{char X[] = { "#ABCBDAB" };char Y[] = { "#BDCABA" };int mx = strlen(X) - 1;int ny = strlen(Y) - 1;vector<vector<int>> c;//二维数组c.resize(mx + 1);//重设容器大小并填充元素(填充vector)for (int i = 0; i < mx + 1; i++){c[i].resize(ny + 1);//重设容器大小并填充元素(字符类型的缺省值)}PrintVector(c);int maxlen = lcsLength(X, Y, mx, ny,c);PrintVector(c);cout << maxlen << endl;
}
这样一来就大大提高了程序的运行效率。
但是这个时候我们只能计算出X和Y的最长公共子序列的长度,不能知道最长公共子序列是具体哪个序列,因此我们再将程序完善:
void PrintVector(vector<vector<int>>& c)
{for (int i = 0; i < c.size(); i++){for (int j = 0; j < c[i].size(); j++){cout << c[i][j] << " ";}cout << endl;}cout << endl;
}
void PrintItem(char *X, int m, int n, vector<vector<int>> &s)
{if (m == 0 || n == 0)return;else{if (s[m][n] == 1){PrintItem(X, m - 1, n - 1, s);cout << X[m] << " ";}else if (s[m][n] == 2){PrintItem(X, m - 1, n, s);}else{PrintItem(X, m, n - 1, s);}}
}
int lcsLength(char *X, char *Y, int m, int n, vector<vector<int>>& c, vector<vector<int>>& s)
{if (m == 0 || n == 0)return 0;else if (c[m][n] > 0) return c[m][n];else{if (X[m] == Y[n]){c[m][n] = lcsLength(X, Y, m - 1, n - 1, c,s) + 1;s[m][n] = 1;//X和Y相等}else{int a = lcsLength(X, Y, m, n - 1, c, s);int b = lcsLength(X, Y, m - 1, n, c, s);if (a > b){c[m][n] = a;s[m][n] = 2;//行-1}else{c[m][n] = b;s[m][n] = 3;//列-1}}return c[m][n];}
}
int main()
{char X[] = { "#ABCBDAB" };char Y[] = { "#BDCABA" };int mx = strlen(X) - 1;int ny = strlen(Y) - 1;vector<vector<int>> c, s;//二维数组c.resize(mx + 1);//重设容器大小并填充元素(填充vector)s.resize(mx + 1);for (int i = 0; i < mx + 1; i++){c[i].resize(ny + 1);//重设容器大小并填充元素(字符类型的缺省值)s[i].resize(ny + 1);}int maxlen = lcsLength(X, Y, mx, ny,c,s);PrintVector(c);PrintVector(s);PrintItem(X, mx, ny, s);cout << endl;cout << maxlen << endl;
}
非递归算法如下:
int NicelcsLength(char* X, char* Y, int m, int n, vector<vector<int>>& c, vector<vector<int>>& s)
{for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){if (X[i] == Y[j]){c[i][j] = c[i - 1][j - 1] + 1;s[i][j] = 1;}else if(c[i - 1][j]> c[i][j - 1]){c[i][j] = c[i - 1][j]; s[i][j] = 2;}else{c[i][j] = c[i][j - 1];s[i][j] = 3;}}}return c[m][n];
}
动态规划----最长公共子序列问题相关推荐
- 动态规划—最长公共子序列问题 HDU-1159 Common Subsequence
动态规划-最长公共子序列问题 Common Subsequence [ HDU - 1159 ] A subsequence of a given sequence is the given sequ ...
- 详解动态规划最长公共子序列--JavaScript实现
前面两篇我们讲解了01背包问题和最少硬币找零问题.这篇将介绍另一个经典的动态规划问题--最长公共子序列.如果没看过前两篇,可点击下面链接. 详解动态规划最少硬币找零问题--JavaScript实现 详 ...
- 动态规划1--最长公共子序列
动态规划1--最长公共子序列 一.动态规划 经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题.简单地采用把大问题分解成子问题,并 综合子问题的解导出大问题的解的方法,问题求解耗时 ...
- 最长公共子序列php,动态规划(最长公共子序列LCS)
概念 求解决策过程最优化的结果 (可能有多个) 把多阶段过程转化为一系列单阶段过程,利用各阶段之间的关系,逐个求解 计算过程中会把结果都记录下,最终结果在记录中找到. 举例 求两个字符串的最长公共子序 ...
- 最长公共子序列动态规划c语言,动态规划----最长公共子序列(C++实现)
最长公共子序列 题目描述:给定两个字符串s1 s2 - sn和t1 t2 - tm .求出这两个字符串的最长公共子序列的长度.字符串s1 s2 - sn的子序列指可以表示为 - { i1 < i ...
- 动态规划--最长公共子序列
1. 子序列 摘自维基百科 在数学中,某个序列的子序列是从最初序列通过去除某些元素但不破坏余下元素的相对位置而形成的新序列. 例如: 令 为一序列 那么,以下序列 是 的子序列之一.对应定义里的自然数 ...
- 动态规划——最长公共子序列(LCS)
最长公共子序列的问题描述为: 下面介绍动态规划的做法. 令 dp[i][j] 表示字符串 A 的 i 号位与字符串 B 的 j 号位之前的 LCS 长度(下标从 1 开始),如 dp[4][5] 表示 ...
- 算法导论之动态规划(最长公共子序列和最优二叉查找树)
动态规划师通过组合子问题的解而解决整个问题,将问题划分成子问题,递归地求解各子问题,然后合并子问题的解而得到原问题的解.和分治算法思想一致,不同的是分治算法适合独立的子问题,而对于非独立的子问题,即各 ...
- 动态规划—最长公共子序列
问题描述:给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度.比如:text1 = "abcde", text2 = "ace" ...
- 【啃不完的算法导论】- 动态规划 - 最长公共子序列(概念篇)
以下内容纯是为了熟悉<算法导论>中的内容,高手可略过,其中涉及的书本内容的版权归原作者.译者.出版社所有 ========================================= ...
最新文章
- 如何配置一台计算机预计3500元,玩游戏用的电脑主机应该怎么配置?3500元组装游戏电脑主机配置推荐...
- html元素移动时颜色逐渐变深,css实现随鼠标移动div渐变色效果
- torch复现论文简明笔记
- getDeclaredFields()应用
- 在 SAP conversation AI 里消费 ABAP OData 服务
- php中getdistance函数_php代码渗透测试 后门分析篇
- Redis事务回滚深入
- mysql 8.0 ~ 安装
- atitit..国富论 在现代it企业项目管理中的作用attialx 总结---国富论读后感 attialx
- mysql数据库安全吗_mysql数据库的安全
- async function
- 两年数据对比柱形图_【Excel技巧】制作柱形图图表完美呈现百分比,提升您的报表颜值...
- jQuery邮票人 --> 案例
- Forest - 轻量级HTTP客户端框架
- 7-56 福到了 (15 分)
- 图像分割-分水岭算法和GrabCut 算法
- Mac 下 Docker搭建RAP2 记录
- 计算机硬件小论文,计算机硬件小论文
- 小波包分解matlab程序
- python目标检测给图画框,bbox画到图上并保存