最长公共子序列(LCS)
来源:互联网 发布:费用优化方案 编辑:程序博客网 时间:2024/06/07 22:57
输入:X=ABCHFGASJKXBD Y=DBDHASXB
输出:LCS=BHASXB
【分析】
最长公共子序列LCS问题可用动态规划算法有效解决。而首先我们需要证明的是,使用动态规划算法的两个基本要素,即为什么最长公共子序列LCS问题可以用动态规划算法来解决。
最长公共子序列问题具有最优子结构性质:
设序列X={x1,x2,x2,……,xm}和Y={y1,y2,y3,……,yn},而Z={z1,z2,z3,……,zk}是X和Y的最长公共子序列。则:
若xm = yn,则zk = xm = yn,Zk-1为Xm-1 和Yn-1的最长公共子序列。
(证:采用反证法,若zk != xm,那么有{z1,z2,z3,……,zk,xm}是为X和Y长度为k+1的最长公共子序列,这与Z是X和Y长度为k的最长公共子序列矛盾。
若Zk-1不是Xm-1和Yn-1的最长公共子序列,则Xm-1和Yn-1具有长度大于k-1的最长公共子序列,那么加上xm后,X和Y的最长公共子序列的长度应该大于k,这与Z是X和Y长度为k的最长公共子序列矛盾。)
若xm != yn 且 zk != xm,则Z是Xm-1和Y的最长公共子序列。
(证:采用反证法,若Z不是Xm-1和Y的最长公共子序列,则Xm-1和Y具有长度大于k的最长公共子序列,那么X和Y的最长公共子序列的长度必定也大于k。这与X和Y具有长度为k的最长公共子序列Z矛盾。)
若xm != yn 且 zk != yn,则Z是X和Yn-1的最长公共子序列。
(证:采用反证法,证法同上述类似)
最长公共子序列问题具有子问题重叠性质。
在寻找X和Y的最长公共子序列时,我们要进行分类讨论:
当xm = yn时,我们要找出Xm-1和Yn-1的最长公共子序列,在其尾部加上xm就为X和Y的最长公共子序列;
当xm != yn时,我们要找出 Xm-1和Y的最长公共子序列和X和Yn-1的最长公共子序列,再比较两者哪个大,即为X和Y的最长公共子序列。
我们可以从中看出,当我们要查找Xm-1和Y的最长公共子序列时,同样也要按照上面所说的步骤进行查找,即有可能要继续查找Xm-2和Y、Xm-1和Yn-1的最长公共子序列;当我们要X和Yn-1的最长公共子序列时,同样也要按照上面所说的步骤进行查找,即有可能要继续查找Xm-1和Yn-1、X和Yn-2的最长公共子序列。在这两个子问题都包含了一个公共子问题,即计算Xm-1和Yn-1的最长公共子序列。
建立LCS问题的递推关系,用c[i][j]表示Xi和Yj的最长公共子序列的长度。其中Xi={x1,x2,……,xi},Yj={y1,y2,……,yj}。
c[i][j] = 0, i = j = 0;
c[i][j] = c[i - 1][j - 1] + 1, xi = yj;
c[i][j] = max{c[i - 1][j], c[i][j - 1]}, xi != yj;
根据递推关系,我们可以写出程序。
【程序】用java语言编写程序,代码如下:
import java.io.BufferedInputStream;import java.util.Scanner;public class LCS {public static void main(String[] args) {Scanner input = new Scanner(new BufferedInputStream(System.in));while(input.hasNext()) {int m = input.nextInt();String sx = input.next();char[] x = new char[m + 1];for(int i = 1; i < m + 1; i++)x[i] = sx.charAt(i - 1);int n = input.nextInt();String sy = input.next();char[] y = new char[n + 1];for(int i = 1; i < n + 1; i++)y[i] = sy.charAt(i - 1);/*int[][] c = new int[m + 1][n + 1];for(int i = 0; i < m + 1; i++)for(int j = 0; j < n + 1; j++)c[i][j] = -1;int len = LCS(m, n, x, y, c);System.out.println();System.out.println(len);*/int[][] c = new int[m + 1][n + 1];int[][] b = new int[m + 1][n + 1];LCSlength(m, n, x, y, c, b);printLCS(m, n, b, x);System.out.println();System.out.println(c[m][n]);}}/*public static int LCS(int m, int n, char[] x, char[] y, int[][] c) {if(m == 0 || n == 0) {c[m][n] = 0;return 0;}//if(c[m][n] != -1)//return c[m][n];if(x[m] == y[n]) {c[m][n] = LCS(m - 1, n - 1, x, y, c) + 1;System.out.print(x[m]);System.out.println(m + " " + n);}else {int lcs1 = LCS(m, n - 1, x, y, c);int lcs2 = LCS(m - 1, n, x, y, c);if(lcs1 > lcs2)c[m][n] = lcs1;elsec[m][n] = lcs2;}return c[m][n];}*/public static void LCSlength(int m, int n, char[] x, char[] y, int[][] c, int[][] b) {int i, j;for(i = 1; i <= m; i++)c[i][0] = 0;for(j = 1; j <= n; j++)c[0][j] = 0;for(i = 1; i <= m; i++)for(j = 1; j <= n; j++) {if(x[i] == y[j]) {c[i][j] = c[i - 1][j - 1] + 1;b[i][j] = 1;}else {if(c[i - 1][j] >= c[i][j - 1]) {c[i][j] = c[i - 1][j];b[i][j] = 2;}else {c[i][j] = c[i][j - 1];b[i][j] = 3;}}}}public static void printLCS(int i, int j, int[][] b, char[] x) {if(i == 0 || j == 0)return;if(b[i][j] == 1) {printLCS(i - 1, j - 1, b, x);System.out.print(x[i]);}else if(b[i][j] == 2)printLCS(i - 1, j, b, x);elseprintLCS(i, j - 1, b, x);}}
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)问题
- 最长公共子序列(LCS)问题
- 求最长公共子序列(LCS)
- 最长公共子序列算法(LCS)
- LCS(最长公共子序列)
- 最长公共子序列(LCS)问题
- 最长公共子序列(LCS问题)
- Coincidence(LCS最长公共子序列)
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)问题
- 最长公共子序列(LCS)问题
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)
- hdu1243 最长公共子序列(LCS)
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)问题
- hdu3652 数位DP
- linux手动编译qt 4.8 , opengl
- n个数出现2次,2个数出现1次,找出这两个数
- 网络分成
- java.lang.OutOfMemoryError: PermGen space及其解决方法
- 最长公共子序列(LCS)
- JS的数据类型
- windows系统System32中各种实用的工具
- convert a byte array to a hexadecimal string
- 第五周【项目2-对象作为数据成员】
- NYOJ 927【The partial sum problem】DFS+剪枝
- 安装VirtualBox虚拟机及详细配置
- 浅拷贝和深拷贝
- sql优化和表优化