最长公共子序列
来源:互联网 发布:单页面网站seo 编辑:程序博客网 时间:2024/06/05 03:11
问题描述:
给定2个序列X={x1, x2,…, xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列
问题分析:
将原问题化为更小的问题可以判断最长公共子序列的结构具有最优子结构的特性
分成以下3种情况,设z为公共子序列数组:
1. 若xm=yn,则zk=xm=yn,且Z(k-1)={z1, z2,…,zk-1 }是X(m-1)= {x1,x2,…,xm-1}和Y(n-1)={y1,y2,…,yn-1}的最长公共子序列。
2. 若xm≠yn且zk≠xm,则Z(k)是x(m-1)和Y(n)的最长公共子序列。
3. 若xm≠yn且zk≠yn,则Z(k)是X(m)和y(n-1)的最长公共子序列
由此可见,2个序列的最长公共子序列包含了这2个序列的前缀(i.e. 子问题)的最长公共子序列。
因此,最长公共子序列问题具有最优子结构性质,可以用动态规划算法自底向上地计算最优值。
设置输出数组b, c, c[i][j]用于存储序列x[i], y[j]的最长公共子序列的长度; b[i][j]记录c[i][j]的值是由哪一个子问题得到的(上述的三个情况),用于构造最长公共子序列。
源程序代码:
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#define maxn 5000using namespace std;char x[maxn]; int b[maxn][maxn], c[maxn][maxn];char A[maxn], B[maxn], C[maxn], D[maxn]; int lcsLength(char x[], char y[], int c[][maxn], int b[][maxn]){ int m = strlen(x); int n = strlen(y); for(int i=0; i<=m; i++) { c[i][0] = 0; } for(int i=0; i<=n; i++) { c[0][i] = 0; } for(int i = 1; i<=m; i++)//i,j在c、b表示个数 { for(int j=1; j<=n; j++) { if(x[i-1] == y[j-1])//情况1 { c[i][j] = c[i-1][j-1] + 1; b[i][j] = 1; } else if(c[i-1][j]>=c[i][j-1])//情况2,谁的子段更长就用谁的子段做原段的子段 { c[i][j] = c[i-1][j]; b[i][j] = 2; } else { c[i][j] = c[i][j-1]; b[i][j] = 3; } } } return c[m][n];}void lcs(int i, int j, char x[], int b[][maxn]){ if(i==0 && j==0) return; if(b[i][j] == 1) { lcs(i-1, j-1, x, b); printf("%c", x[i-1]); } else if(b[i][j] == 2) lcs(i-1, j, x, b); else lcs(i, j-1, x, b);}int main(){ int length; int la, lb, lc, ld;//各序列的长度 cout<<"输入字符串A:"<<endl; scanf("%s", A); cout<<"输入字符串B:"<<endl; scanf("%s", B); cout<<"输入字符串C:"<<endl; scanf("%s", C); cout<<"输入字符串D:"<<endl; scanf("%s", D); la = strlen(A); lb = strlen(B); lc = strlen(C); ld = strlen(D); /*A、B序列的长公共子序列*/ memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); length = lcsLength(A, B, c, b); cout<<"A-B最长子序列长度为:"<<length<<endl; cout<<"序列为:"; lcs(la, lb, A, b); cout<<endl; /*C、D的最长公共子序列*/ memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); length = lcsLength(C, D, c, b); cout<<"C-D最长子序列长度为:"<<length<<endl; cout<<"序列为:"; lcs(lc, ld, C, b); cout<<endl; /*A-D*/ memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); length = lcsLength(A, D, c, b); cout<<"A-D最长子序列长度为:"<<length<<endl; cout<<"序列为:"; lcs(la, ld, A, b); cout<<endl; /*C-B*/ memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); length = lcsLength(C, B, c, b); cout<<"C-B最长子序列长度为:"<<length<<endl; cout<<"序列为:"; lcs(lc, lb, C, b); cout<<endl; return 0;}
阅读全文
0 0
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列...
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- H5研究五:菊花加载动画JS
- servlet的部分作用域和接口简介
- 【H.264/AVC视频编解码技术详解】十五、H.264的变换编码(二):H.264整数变换和量化的实现
- 手势识别 opencv 代码
- 信号屏蔽pending
- 最长公共子序列
- Android N(7.0) SystemUI-Notification
- 【JavaScript的弹窗】
- Asp.net MVC 中Controller返回值类型ActionResult
- 人脸检测和识别及python实现系列(1)-- 环境配置和相关类库安装
- 一个时代的终结:ImageNet 竞赛 2017 是最后一届
- 作用域和Fiilter过滤器
- LeeCode Median of Two Sorted Arrays
- Redis学习笔记一:redis简介及安装使用