1、先科普下最长公共子序列 & 最长公共子串的区别:
找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。而最长公共子序列则并不要求连续。
2、最长公共子串
其实这是一个序贯决策问题,可以用动态规划来求解。我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab")
b a b
c 0 0 0
a 0 1 0
b 1 0 1
a 0 1 0
我们看矩阵的斜对角线最长的那个就能找出最长公共子串。
不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。
b a b
c 0 0 0
a 0 1 0
b 1 0 2
a 0 2 0
这样矩阵中的最大元素就是 最长公共子串的长度。
在构造这个二维矩阵的过程中由于得出矩阵的某一行后其上一行就没用了,所以实际上在程序中可以用一维数组来代替这个矩阵。
实现代码:
public class maxOfStr {
public static void main(String[] args) {
// TODO Auto-generated method stub
String str1 = "mabcdf", str2 = "kfcdabck";
char[] arr1 = str1.toCharArray();
char[] arr2 = str2.toCharArray();
int res[][] = new int[arr1.length+2][arr2.length+2]; //外面建一堵墙,全部为0,防止求左上角元素时数组越界
int max=0;
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr2.length; j++) {
if (arr1[i]==arr2[j]) {
if (res[i][j]>0) {
res[i+1][j+1]=res[i][j]+1;
}else {
res[i+1][j+1]=1;
}
max=Math.max(res[i+1][j+1], max);
}
}
}
System.out.println(max);
}
}
public class LCS { public static void main(String[] args) { String a = "ddhehekabc"; String b = "deekrtabc"; fun(0, 0, a.toCharArray(), b.toCharArray()); System.out.println(max); } static String max = ""; static String temp = ""; public static void fun(int startA, int startB, char[] a, char[] b) { if (startA == a.length || startB == b.length) return; for (int i = startA; i < a.length; i++) { for (int j = startB; j < b.length; j++) { if (a[i] == b[j]) { temp = temp + a[i]; if (temp.length() > max.length()) { max = temp; } fun(i + 1, j + 1, a, b); } else { temp = ""; } } } } }
测试结果: