动态规划之最长公共子序列
来源:互联网 发布:吴江js华腾公寓自提柜 编辑:程序博客网 时间:2024/06/07 02:29
先来看一下基本概念
1、公共子序列:给定两个序列X和Y,如果Z既是X的子序列,又是Y的子序列,那么称Z是X和Y的公共子序列。
2、最长公共子序列:求公共子序列中长度最长的。
最长公共子序列问题,简称LCS问题,下边说一下求解思路:
步骤一:刻画最长公共子序列的特征:
前缀:给定一个序列X={x1,x2,x3...xm},对于i=1...m,定义X的第i前缀Xi={x1,x2,..xi};
结论:两序列的LCS包含两序列的前缀的LCS。因此,LCS问题具有最优子结构性质。
步骤二:
定义c[i,j]表示X和Y的LCS长度,下边给出递归式:
步骤三:
自底向上的动态规划方法:
void LCS_down2up(DataType X[],int m,DataType Y[],int n,int c[M+1][N+1],char b[M+1][N+1]){ for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { if(X[i-1]==Y[j-1]) { c[i][j]=c[i-1][j-1]+1; b[i][j]='D'; //D means diagonal(对角线) } else { c[i][j]=max(c[i-1][j],c[i][j-1]); if(c[i-1][j]>c[i][j-1]) b[i][j]='T'; // T means top else b[i][j]='L'; // L means left } } }}c数组保存最大子序列长度,b数组记录子问题的调用方向
步骤四、构造LCS
void print_result(char b[M+1][N+1],DataType X[],int i,int j){ if(i==0 || j==0) ; else { if(b[i][j]=='D') { print_result(b,X,i-1,j-1); cout<<X[i-1]; } else if(b[i][j]=='T') print_result(b,X,i-1,j); else print_result(b,X,i,j-1); }}
其实最大公共子序列并非只有一个,我们所做的只是找出了满足条件的一个最优解而已,所以在运行测试代码时,我们构造解的起点不同,最后打印的LCS也不同。
测试代码
#include <iostream>#define M 7#define N 6typedef char DataType;using namespace std;//down to topvoid LCS_down2up(DataType X[],int m,DataType Y[],int n,int c[M+1][N+1],char b[M+1][N+1]){ for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { if(X[i-1]==Y[j-1]) { c[i][j]=c[i-1][j-1]+1; b[i][j]='D'; //D means diagonal(对角线) } else { c[i][j]=max(c[i-1][j],c[i][j-1]); if(c[i-1][j]>c[i][j-1]) b[i][j]='T'; // T means top else b[i][j]='L'; // L means left } } }}void print_result(char b[M+1][N+1],DataType X[],int i,int j){ if(i==0 || j==0) ; else { if(b[i][j]=='D') { print_result(b,X,i-1,j-1); cout<<X[i-1]; } else if(b[i][j]=='T') print_result(b,X,i-1,j); else print_result(b,X,i,j-1); }}int main(){ DataType X[]={'a','b','c','b','d','a','b'},Y[]={'b','d','c','a','b','a'}; int c[M+1][N+1]={0}; char b[M+1][N+1]={0}; LCS_down2up(X,M,Y,N,c,b); cout<<"the list of result : "<<endl; for(int i=1;i<M+1;i++) { for(int j=1;j<N+1;j++) { cout<<c[i][j]<<"\t"; } cout<<endl; } cout<<"b list:"<<endl; for(int i=1;i<M+1;i++) { for(int j=1;j<N+1;j++) { cout<<b[i][j]<<"\t"; } cout<<endl; } print_result(b,X,6,6); cout<<endl; print_result(b,X,7,6); return 0;}
阅读全文
0 0
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- 动态规划之最长公共子序列
- mybatis 中 foreach collection的三种用法
- uva141
- 2017-11-4离线赛总结
- Dalvik指令解析示例
- Tomcat7.0.42源码研读之组件生命周期Lifecycle(一)
- 动态规划之最长公共子序列
- C
- 51Nod
- 你真的了解过度绘制吗?
- 使用gdb调试的一般步骤
- 修改centos6&rhel6.5支持auto resize the root partition
- 博客园博客地址
- 【区块链】Decentraland 挖矿教学
- 算法 分治 平面最近点对