https://www.lintcode.com/problem/77
给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。
最长公共子序列的定义:
最长公共子序列问题是在一组序列(通常2个)中找到最长公共子序列(注意:不同于子串,LCS不需要是连续的子串)。该问题是典型的计算机科学问题,是文件差异比较程序的基础,在生物信息学中也有所应用。
https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
样例
样例 1:
输入:
A = "ABCD"
B = "EDCA"
输出:
1
解释:
LCS是 'A' 或 'D' 或 'C'
样例 2:
输入:
A = "ABCD"
B = "EACB"
输出:
2
解释:
LCS 是 "AC" 或 "AB"
public class Solution {
/**
* @param a: A string
* @param b: A string
* @return: The length of longest common subsequence of A and B
*/
public int longestCommonSubsequence(String a, String b) {
if (a == null || b == null || a.length() == 0 || b.length() == 0)
return 0;
//单纯递归,超时
//int ans = dfs1(a.toCharArray(), b.toCharArray(), a.length() - 1, b.length() - 1);
//动态规划,或者递归+缓存也行,这里先用动态规划来做
int ans = dfs2(a.toCharArray(), b.toCharArray());
return ans;
}
public static int dfs1(char[] str1, char[] str2, int i, int j) {
if (i == 0 && j == 0) {
return str1[i] == str2[j] ? 1 : 0;
} else if (i == 0) {
if (str1[i] == str2[j]) {
return 1;
} else {
return dfs1(str1, str2, i, j - 1);
}
} else if (j == 0) {
if (str1[i] == str2[j]) {
return 1;
} else {
return dfs1(str1, str2, i - 1, j);
}
} else {
int p1 = dfs1(str1, str2, i - 1, j);
int p2 = dfs1(str1, str2, i, j - 1);
int p3 = str1[i] == str2[j] ? (1 + dfs1(str1, str2, i - 1, j - 1)) : 0;
return Math.max(p1, Math.max(p2, p3));
}
}
public static int dfs2(char[] str1,char[] str2){
int n =str1.length;
int m = str2.length;
int[][] dp = new int[n+1][m+1];
dp[0][0]= str1[0]==str2[0]?1:0;
for (int i = 1; i <m ; i++) {
dp[0][i] = str1[0] == str2[i]?1:0;
}
for (int i = 1; i <n ; i++) {
dp[i][0] = str1[i] == str2[0]?1:0;
}
int ans = 0;
for (int i = 1; i <n ; i++) {
for (int j = 1; j <m ; j++) {
int p1 = dp[i-1][j];
int p2 = dp[i][j-1];
int p3 = str1[i]==str2[j]?(1+dp[i-1][j-1]):0;
dp[i][j] = Math.max(p1,Math.max(p2,p3));
}
}
return dp[n-1][m-1];
}
}