动态规划----最长公共子序列
来源:互联网 发布:winscp linux版 编辑:程序博客网 时间:2024/06/06 15:02
最长公共子序列
1.问题的理解与描述
最长公共子序列(LCS)问题形式化为:
输入:序列X = <x1, x2, ..., xm>
和Y = <y1, y2, ..., yn>
。
输出:X与Y的一个最长公共子序列Z。
- 最优子结构与子问题的重叠
定理3-1(最长公共子序列的最优子结构)
设X = <x1, x2, ..., xm>
和Y = <y1, y2, ..., yn>
为两个序列,并设Z = <z1, z2, ..., zk>
为X 和Y的任一LCS。
(1)若xm = yn,则zk = xm = yn且Zk-1是Xm-1和Yn-1的一个LCS。
(2)若xm ≠ yn,则zk ≠ xm蕴含着Z是Xm-1和Y的一个LCS。
(3)若xm ≠ yn,则zk ≠ yn蕴含着Z是X 和Yn-1的一个LCS。
设c[i, j]为子序列Xi和Yj的LCS的长度。根据最长公共子序列问题的最优子结构得出下列递归式:
eg:
3.算法的伪代码描述
LCS-LENGTH (X, Y)1 m ← length[X]2 n ← length[Y]3 for i ← 1 to m4 do c[i, 0] ← 0 5 for j ← 0 to n6 do c[0, j] ← 0 7 for i ← 1 to m8 do for j ← 1 to n9 do if xi = yj10 then c[i, j] ← c[i - 1, j - 1] + 111 else if c[i - 1, j] c[i, j - 1]12 then c[i, j] ← c[i - 1, j]13 else c[i, j] ← c[i, j - 1]15 return c
4.构造一个最优解
PRINT-LCS(c, X, Y, i, j)1 if i = 0 or j = 02 then return3 if xi = yj4 then PRINT-LCS (c, X, Y, i - 1, j - 1)5 print xi6 elseif c[i - 1, j] c[i, j - 1]7 then PRINT-LCS (c, X, Y, i - 1, j)8 else PRINT-LCS (c, X, Y, i, j - 1)
5.算法的运行时间
过程LCS-LENGTH的主体是第7~8行两重嵌套的for循环,容易看出其时间复杂度为T(m, n)= Θ(mn),其中m,n分别为X和Y的长度。而过程PRINT-LCS的时间复杂度为T(m, n)= Θ(m+n)。
6 代码实现:
#ifndef _LCS_H#define _LCS_H#include<iostream>using namespace std;template<typename Iterator>int* lcsLength(Iterator x, Iterator y, int m, int n){ int i, j; int*c = new int[(m + 1)*(n + 1)]; for (i = 1; i <= m; i++) c[i*(n + 1)] = 0;//c[i,0]=0 for (j = 0; j <= n; j++) c[j] = 0;//c[0,j]=0; for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) if (*(x + i-1) == *(y + j-1))//x[i]=y[j] c[i*(n + 1) + j] = c[(i - 1)*(n + 1) + j - 1] + 1;//c[i,j]=c[i-1,j-1] else if (c[(i - 1)*(n + 1) + j] >= c[i*(n + 1) + j - 1])//c[i-1,j]>=c[i,j-1] c[i*(n + 1) + j] = c[(i - 1)*(n + 1) + j]; else c[i*(n + 1) + j] = c[i*(n + 1) + j - 1]; return c;}template<typename Iterator>void printLcs(int *c, int n, Iterator x, Iterator y, int i, int j){ if (i == 0 || j == 0) return; if (*(x + i - 1) == *(y + j - 1)) { printLcs(c, n, x, y, i - 1, j - 1); cout << *(x + i - 1); } else if (c[(i - 1)*(n + 1) + j] >= c[i*(n + 1) + j - 1]) printLcs(c, n, x, y, i - 1, j); else printLcs(c, n, x, y, i, j - 1);}#endif
#include <cstdlib>#include "lcs.h"int main(int arge, char** argv){ char*x = "ACCGGTCGAGTGCGCGGAAGCCGGCCGAA"; char*y = "GTCGTTCGGAATGCCGTTGCTCTGTAAA"; int *c; c = lcsLength(x, y, 29, 28); printLcs(c, 28, x, y, 29, 28); cout << endl; delete[]c; system("pause"); return EXIT_SUCCESS;}
运行结果:
参考:徐子珊–《算法设计、分析与实现:C、C++和 Java》
0 0
- 最长公共子序列&&最长公共子串---[动态规划]
- 动态规划-最长公共子序列、最长公共子串
- 动态规划之最长公共子序列
- 动态规划 ------- 最长公共子序列
- 动态规划实现最长公共子序列
- 【动态规划】最长公共子序列LCS
- 动态规划--最长公共子序列
- 动态规划:最长公共子序列
- 动态规划解决最长公共子序列
- 最长公共子序列-动态规划DP
- 动态规划--最长公共子序列
- 最长公共子序列(动态规划)
- 动态规划解决最长公共子序列
- 最长公共子序列(动态规划)
- 动态规划 最长公共子序列
- 动态规划 - 最长公共子序列
- 动态规划之最长公共子序列
- 最长公共子序列 [动态规划]
- JAVA 内存管理总结
- 简析Hadoop的三种运行模式
- 反弹stage shellcode到meterpreter
- java内存空间详解
- minicom
- 动态规划----最长公共子序列
- ubuntu php版本更新
- Debian下MySQL安装
- Ionic开发过程记录: Activity之间数据交流(onActivityResult的用法)
- 菜鸟学安卓Log.v("第一篇")——为何突然想写安卓学习的博客?
- SimpleDateFormat线程不安全
- JDBC连接Mysql实现数据的插入、更改操作
- Isomorphic Strings
- fork和vfork的区别