5、最长公共子序列

来源:互联网 发布:破解手机收费软件 编辑:程序博客网 时间:2024/06/08 10:19

(1)问题

给定两个序列X={x1,x2,...,xm}和Y={y1,y2,...yn},找出X和Y的最长公共子序列.

(2)分析

用c[i][j]记录序列Xi和Yj的最长公共子序列的长度,可建立递归关系如图1:


图1

用b[i][j]记录c[i][j]的值是由哪一个子问题的解得到的,输出最长公共子序列的过程如图2,在算法lcs中,每一次递归调用使i或j减1(或同时减1),故最多调用m+n次就使得i=0,或j=0,因此,时间复杂度为O(m+n).


图2

(3)实现

package com.test;public class Test {static String str1 = "ABCBDAB";static String str2 = "BDCABA";public static void main(String[] args) {char[] x = str1.toCharArray();char[] y = str2.toCharArray();int[][] b = new int[x.length + 1][y.length+1];int[][] c = new int[x.length + 1][y.length+1];lcsLength(x, y, x.length, y.length, c, b);System.out.print(str1+"与"+str2+"的最长公共子序列为:");lcs(x, b, x.length, y.length);}public static void lcsLength(char[] x, char[] y, int m, int n, int[][] c, int[][] b) {for (int i = 0; i <= m; i++) {c[i][0] = 0;}for (int i = 1; i <= n; i++) {c[0][i] = 0;}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] = 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 lcs(char[] x ,int[][] b,int i,int j) {if (i == 0 || j == 0) {return;}if (b[i][j] == 1) {lcs(x, b, i-1, j-1);System.out.print(x[i-1]);}else if (b[i][j] == 2) {lcs(x, b, i-1, j);}else {lcs(x, b, i, j-1);}}}

(4)运行结果




0 0