一、解题思路
看到这题,我们先得知道怎么求最长公共子序列。
对于串A:a1,a2…an;串B:b1,b2…bm;我们将求子串定为F(n,m);
我们先比较an和bm两个字符,会有两种情况
如果相等,我们就会继续比较除最后一个字符的两个串,此时的公共子序列则为an;
an == bm ,F(n,m) = F(n-1,m-1)+an;如果不相等,则去比较 an和b(m-1) 或者 a(n-1)和bm ,选出其中子串最长的一个作为结果;
an != bm, F(n,m) = Max(F(n,m-1),F(n-1,m));
这样一直比较到某串为空时,则结束。
注意:子序列并不要求连续,因此对于A串“abccd801” 和
B串“oabcdv8100”,它们的最长公共子序列为“abcd81”。但如果是最长公共子字符串的话,则为“abc”。
二、代码
public class LongestCommonSub {
//最长公共子序列的公共子序列里的元素可以不相邻,但是公共子字符串必须是连接在一起的,比如A和B的公共子字符串是“abcd81”。
public static final String A = "abccd801";
public static final String B = "oabcdv8100";
public static String findLongestCommonSub(String a, String b) {
if (a == null || b == null) {
return "";
}
if (a.length() == 0 || b.length() == 0) {
return "";
}
if (a.length() == 1) {
if (b.contains(a)) {
return a;
}
}
if (b.length() == 1) {
if (a.contains(b)) {
return b;
}
}
return findString(a, b, "");
}
private static String findString(String a, String b, String sameString) {
if (a.length() == 0 || b.length() == 0) {
return String.valueOf(sameString);
}
String result;
if (getEndChar(a) == getEndChar(b)) {
sameString = getEndChar(a) + sameString;
result = findString(getUnEndString(a), getUnEndString(b), sameString);
} else {
String resultA = findString(getUnEndString(a), b, sameString);
String resultB = findString(a, getUnEndString(b), sameString);
result = resultA.length() > resultB.length() ? resultA : resultB;
}
return result;
}
private static char getEndChar(String s) {
return s.charAt(s.length() - 1);
}
private static String getUnEndString(String s) {
return s.substring(0, s.length() - 1);
}
}