java实现LSC最大公有子序列



java实现LSC最大公有子序列实例代码。java源码教程。

package com.stone.study.core;

/**
*
* @ClassName LSC
* @Description TODO
* 最长公有子序列
* 算法类型:动态规划
*
* 问题描述:如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字符串二的子串。
* 注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中。
* 请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串。
* 例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子序列,则输出它们的长度4,并打印任意一个子序列。
*
* 转移方程:
* dp[i,j] = 0 i=0 || j=0
* dp[i,j] = dp[i-1][j-1]+1 i>0,j>0, a[i] = b[j]
* dp[i,j] = max(dp[i-1][j],dp[i][j-1]) i>0,j>0, a[i] != b[j]
*
* @author stone
* @date:2014-4-3上午10:34:16
*/
public class LSC {

public static char[] s1 = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’ };
public static char[] s2 = { ‘b’, ‘c’, ‘a’, ‘e’, ‘f’, ‘g’, ‘h’, ‘a’ };

/**
* c[i][j]保存s1第0到i之间的字符串与s2第0到j之间的字符串,最长公有子串长度,因此c为[s1.length+1][s2.length+1]
*/
static int[][] c = new int[s1.length + 1][s2.length + 1];

/**
* b[i][j]保存s1中第0到i之间的字符串与s2第0到j之间的字符串,最后一个字符针对最长公有子串的比较结果
*/
static char[][] b = new char[s1.length + 1][s2.length + 1];
public static void main(String[] args) {
lsc();
/*
* 打印: 6
*/


printLsc();
/*
* 打印:bcefgh
*/
}

/**
* 计算子问题结果,并存入c数组中
*/
public static void lsc() {

for (int i = 0; i < c.length; i++) {
c[i][0] = 0;
}
for (int j = 0; j < c[0].length; j++) {
c[0][j] = 0;
}

int m = s1.length + 1;
int n = s2.length + 1;
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (s1[i - 1] == s2[j - 1]) {
c[i][j] = c[i - 1][j - 1] + 1;
b[i][j] = s1[i - 1];
} else if (c[i][j - 1] >= c[i - 1][j]) {
b[i][j] = ‘左’;
c[i][j] = c[i][j - 1];
} else {
c[i][j] = c[i - 1][j];
b[i][j] = ‘上’;
}
}
}
System.out.println(c[m-1][n-1]);
}

/**
* 根据b数组中存储的结果路径,打印子串
*/
public static void printLsc() {
StringBuilder stringBuilder = new StringBuilder();

int i = b.length – 1;
int j = b[i].length – 1;
while (i > 0 && j > 0) {
if (b[i][j] == ‘左’) {
j–;
} else if (b[i][j] == ‘上’) {
i–;
} else {
stringBuilder.append(b[i][j]);
i–;
j–;
}
}
System.out.println(stringBuilder.reverse().toString());
}
}