Given two strings, find the longest common subsequence (LCS).
Your code should return the length of LCS.
Example
Example 1:
Input: "ABCD" and "EDCA"
Output: 1
Explanation:
LCS is 'A' or 'D' or 'C'
Example 2:
Input: "ABCD" and "EACB"
Output: 2
Explanation:
LCS is "AC"
Clarification
What's the definition of Longest Common Subsequence?
思路:看最后一步,f[i][j] 表示下标为Ai, Bj的数,能够表示的longest common subsequence是多少;
状态转移方程:f[i][j] = Max{f[i][j-1], f[i-1][j], f[i-1][j-1] | A[i] = B[j]};
注意如果Ai == Bj, 要+1,因为好不容易匹配上一个,需要长度+1;
注意:因为要用到f[n][m]所以申请f[n+1][m+1]大小的数组; Time O(n*m) Space(n*m);
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length();
int n = text2.length();
int[][] dp = new int[m + 1][n + 1];
for(int i = 0; i <= m; i++) {
for(int j = 0; j <= n; j++) {
if(i == 0 || j == 0) {
dp[i][j] = 0;
} else {
if(text1.charAt(i - 1) != text2.charAt(j - 1)) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
} else {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1);
}
}
}
}
return dp[m][n];
}
}
因为状态转移方程只跟f[i] 和f[i-1] 上一层有关系,所以可以用滚动数组优化到O(M)
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length();
int n = text2.length();
int[][] dp = new int[2][n + 1];
// calculate matrix;
for(int i = 0; i <= m; i++) {
for(int j = 0; j <= n; j++) {
if(i == 0 || j == 0) {
dp[i % 2][j] = 0;
} else {
dp[i % 2][j] = Math.max(dp[(i - 1) % 2][j], dp[i % 2][j - 1]);
if(text1.charAt(i - 1) == text2.charAt(j - 1)) {
dp[i % 2][j] = Math.max(dp[i % 2][j], dp[(i - 1) % 2][j - 1] + 1);
}
}
}
}
return dp[m % 2][n];
}
}
打印路径,也就是打印出最长子序列代码:
思路:用pi数组记录当时f[i][j]是怎么来的,是砍掉A的尾巴,还是B的尾巴,还是A和B的尾巴match;然后反向输出得到的;
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length();
int n = text2.length();
int[][] dp = new int[m + 1][n + 1];
int[][] pie = new int[m + 1][n + 1];
for(int i = 0; i <= m; i++) {
for(int j = 0; j <= n; j++) {
if(i == 0 || j == 0) {
dp[i][j] = 0;
} else {
if(text1.charAt(i - 1) != text2.charAt(j - 1)) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
if(dp[i][j] == dp[i - 1][j]) {
pie[i][j] = 1;
}
if(dp[i][j] == dp[i][j - 1]) {
pie[i][j] = 0;
}
} else {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1);
if(dp[i][j] == dp[i - 1][j - 1] + 1) {
pie[i][j] = 2;
}
}
}
}
}
StringBuilder sb = new StringBuilder();
int i = m; int j = n;
int len = dp[m][n];
while(len > 0) {
if(pie[i][j] == 2) {
sb.insert(0, text1.charAt(i - 1));
i--;
j--;
len--;
} else if(pie[i][j] == 0) {
j--;
} else {
i--;
}
}
System.out.println("common str is:" + sb.toString());
return dp[m][n];
}
}