经典DP之两字符串最长公共子序列
转载请注明作者与出处:franciscolv http://www.cnblogs.com/franciscolv/archive/2011/11/20/2255858.html
分为连续子串和非连续子串。
package SortSet;
/**
* 最长公共子序列 连续 非连续
*
* @author franciscolv
*
*/
public class LCS {
private static char[] result;
private static int posj;
public static void main(String[] args) {
String s = "ABCDEFGABCAGD";
String t = "ABCDFGABCDGD";
System.out.println("非连续最长公共子串为长度为:"
+ lcs(s.toCharArray(), t.toCharArray()));
System.out.println("非连续最长公共子串为:");
for (char c : result)
System.out.print(c);
System.out.println();
int k = lcs2(s.toCharArray(), t.toCharArray());
System.out.println("连续最长公共子串为长度为:" + k);
System.out.println("连续最长公共子串为:");
for (int i = posj - k + 1; i < posj + 1; i++)
System.out.print(t.charAt(i));
System.out.println();
}
/**
* o(n*n) 最长连续公共子序列
*
* @param c
* @param b
* @return
*/
public static int lcs2(char[] c, char[] b) {
int[][] m = new int[c.length + 1][b.length + 1];
for (int i = 1; i <= c.length; i++) {
for (int j = 1; j <= b.length; j++) {
if (c[i - 1] == b[j - 1]) {
m[i][j] = m[i - 1][j - 1] + 1;
} else
m[i][j] = 0;
}
}
return max(m, c.length + 1, b.length + 1);
}
private static int max(int[][] m, int len1, int len2) {
int max = -1;
for (int i = 1; i < len1; i++)
for (int j = 1; j < len2; j++)
if (m[i][j] > max) {
max = m[i][j];
posj = j - 1;
}
return max;
}
/**
* 非连续最长公共子序列 o(n*n)
*
* @param c
* @param b
* @return
*/
public static int lcs(char[] c, char[] b) {
int[][] m = new int[c.length + 1][b.length + 1];
int[][] s = new int[c.length + 1][b.length + 1];
for (int i = 1; i <= c.length; i++) {
for (int j = 1; j <= b.length; j++) {
if (c[i - 1] == b[j - 1]) {
m[i][j] = m[i - 1][j - 1] + 1;
} else {
if (m[i - 1][j] > m[i][j - 1]) {
m[i][j] = m[i - 1][j];
s[i][j] = -1;
} else {
m[i][j] = m[i][j - 1];
s[i][j] = 1;
}
}
}
}
int p = c.length, q = b.length, k = m[p][q];
if (k > 0) {
result = new char[k];
while (p > 0 && q > 0) {
switch (s[p][q]) {
case -1:
p--;
break;
case 0:
result[--k] = c[p - 1];
p--;
q--;
break;
case 1:
q--;
break;
}
}
}
return m[c.length][b.length];
}
}