算法之最长公共子序列(动态规划)
2016-11-23 20:00
489 查看
问题描述:
最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。而最长公共子串(要求连续)和最长公共子序列是不同的。
举例说明:
设有两个字符串 x,y ,其中 x={′′qwertyuiop′′} y={′′qwrtiopsd′′}
那么 LCS(x,y)=′′qwrtiop′′
算法分析:
我们知道动态规划具有最优子结构性质和重叠子问题性质,其实 LCS 也具有最优子结构性质,设有 字符串 Xm=x1x2...xm,Yn=y1y2...yn, LCS(Xm,Yn)=Zk=z1z2...zk那么就有:
1) 当xm=yn 的时候就有LCS(Xm,Yn) = LCS(Xm−1,Yn−1)+1
2) 当xm!=yn, xm!=zk 的时候就有LCS(Xm,Yn) = LCS(Xm−1,Yn)
3) 当xm!=yn, yn!=zk 的时候就有LCS(Xm,Yn) = LCS(Xm,Yn−1)
那么我们设有 dp[i][j] 表示的是:以 xi 为结尾的与 以 yj 为结尾最长公共子序列的长度。
那么有 dp[i][j]=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪0,dp[i−][j−1]+1max(dp[i−1][j],dp[i][j−1])if i<=0||j<=0 if xi=yj xi!=yj
所以我们可以根据状态转移方程计算出 LCS(Xm,Yn)
然后我们将其打印出来,怎么打印呢,其实这里有一个敲门:就是用一个数组分别记录以上三种情况,然后递归打印就行,具体参照打印函数LCS。
运行后的截图:
最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。而最长公共子串(要求连续)和最长公共子序列是不同的。
举例说明:
设有两个字符串 x,y ,其中 x={′′qwertyuiop′′} y={′′qwrtiopsd′′}
那么 LCS(x,y)=′′qwrtiop′′
算法分析:
我们知道动态规划具有最优子结构性质和重叠子问题性质,其实 LCS 也具有最优子结构性质,设有 字符串 Xm=x1x2...xm,Yn=y1y2...yn, LCS(Xm,Yn)=Zk=z1z2...zk那么就有:
1) 当xm=yn 的时候就有LCS(Xm,Yn) = LCS(Xm−1,Yn−1)+1
2) 当xm!=yn, xm!=zk 的时候就有LCS(Xm,Yn) = LCS(Xm−1,Yn)
3) 当xm!=yn, yn!=zk 的时候就有LCS(Xm,Yn) = LCS(Xm,Yn−1)
那么我们设有 dp[i][j] 表示的是:以 xi 为结尾的与 以 yj 为结尾最长公共子序列的长度。
那么有 dp[i][j]=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪0,dp[i−][j−1]+1max(dp[i−1][j],dp[i][j−1])if i<=0||j<=0 if xi=yj xi!=yj
所以我们可以根据状态转移方程计算出 LCS(Xm,Yn)
然后我们将其打印出来,怎么打印呢,其实这里有一个敲门:就是用一个数组分别记录以上三种情况,然后递归打印就行,具体参照打印函数LCS。
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> using namespace std; const int MAXN = 1e3+5; char x[MAXN], y[MAXN]; int lenx, leny; int dp[MAXN][MAXN], dep[MAXN][MAXN]; void LCS(int i, int j, char x[], int b[][MAXN]){ if(i==lenx+1 || j==leny+1) return ; if(b[i][j] == 1){ cout<<x[i]; LCS(i+1, j+1, x, b); } if(b[i][j] == 2) LCS(i, j+1, x, b); if(b[i][j] == 3) LCS(i+1, j, x, b); } int main() { while(1){ puts("请输入两个字符串:"); scanf("%s%s",x+1,y+1); lenx = strlen(x+1); leny = strlen(y+1); memset(dp, 0, sizeof(dp)); memset(dep, 0, sizeof(dep)); for(int i=1; i<=lenx; i++){ for(int j=1; j<=leny; j++){ if(x[i] == y[j]){ dp[i][j] = dp[i-1][j-1]+1; dep[i][j] = 1; } else { if(dp[i-1][j] > dp[i][j-1]) dep[i][j] = 2; else dep[i][j] = 3; dp[i][j] = max(dp[i-1][j], dp[i][j-1]); } } } puts("他们两个的最长公共子序列的长度为:"); cout<<dp[lenx][leny]<<endl; puts("他们的最长公共子序列是:"); LCS(1, 1, x, dep); puts(""); puts("按任意键继续:"); char ch; scanf("%s",&ch); } return 0; }
运行后的截图:
相关文章推荐
- 最长公共子序列 分类: 算法 动态规划 2014-10-27 21:50 72人阅读 评论(0) 收藏
- 算法知识之最长公共子序列问题(动态规划)
- LCS算法[动态规划 最长公共子序列]求回文串
- 算法 动态规划 最长公共子序列问题
- 【算法】 动态规划 最长公共子序列
- 【算法】动态规划经典题之最长公共子序列
- 蓝桥杯 ADV-202算法提高 最长公共子序列(动态规划)
- Python实现各类数据结构和算法---动态规划之最长公共子序列
- 最长公共子序列和回文字符串 动态规划 小白算法练习
- 【算法导论学习-29】动态规划经典问题02:最长公共子序列问题(Longest common subsequence,LCS)
- 经典算法学习_动态规划_最长公共子序列
- 0011算法笔记——【动态规划】最长公共子序列问题(LCS)
- [动态规划] [LCS算法] 最长公共子序列 longest common subsequence
- 【算法导论实验4】动态规划-最长公共子序列LCS
- 夕拾算法进阶篇:15)最长公共子序列(动态规划DP)
- 【啃不完的算法导论】- 动态规划 - 最长公共子序列(概念篇)
- [算法笔记]动态规划之最长公共子串和最长公共子序列
- 【算法导论】动态规划之最长公共子序列
- [算法]动态规划之最长公共子序列
- 【算法导论学习-29】动态规划经典问题02:最长公共子序列问题(Longest common subsequence,LCS)