Geeks面试题: Longest Common Subsequence (LCS)
Longest Common Subsequence
We have discussed Overlapping Subproblems and Optimal Substructure properties in Set 1 and Set 2respectively. We also discussed one example problem in Set 3. Let us discuss Longest Common Subsequence (LCS) problem as one more example problem that can be solved using Dynamic Programming.
LCS Problem Statement: Given two sequences, find the length of longest subsequence present in both of them. A subsequence is a sequence that appears in the same relative order, but not necessarily contiguous. For example, “abc”, “abg”, “bdf”, “aeg”, ‘”acefg”, .. etc are subsequences of “abcdefg”. So a string of length n has 2^n different possible subsequences.
It is a classic computer science problem, the basis of diff (a file comparison program that outputs the differences between two files), and has applications in bioinformatics.
Examples:
LCS for input Sequences “ABCDGH” and “AEDFHR” is “ADH” of length 3.
LCS for input Sequences “AGGTAB” and “GXTXAYB” is “GTAB” of length 4.
递归法:
int lcs(char *c1, int m, char *c2, int n) { if (m == 0 || n == 0) return 0; if (c1[m-1] == c2[n-1]) { return 1 + lcs(c1, m-1, c2, n-1); } else { return max(lcs(c1, m-1, c2, n), lcs(c1, m, c2, n-1)); } }
二维动态规划法:
int lcsDP(char *c1, int m, char *c2, int n) { vector<vector<int> > ta(m+1, vector<int>(n+1)); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (c1[i] == c2[j]) ta[i+1][j+1] = ta[i][j]+1; else { ta[i+1][j+1] = max(ta[i][j+1], ta[i+1][j]); } } } return ta[m][n]; }
2个一维表:
int lcsDP2(char *c1, int m, char *c2, int n) { vector<vector<int> > ta(2, vector<int>(n+1)); bool flag = false; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (c1[i] == c2[j]) { ta[flag][j+1] = ta[!flag][j] + 1; } else { ta[flag][j+1] = max(ta[!flag][j+1], ta[flag][j]); } } flag = !flag; } return ta[!flag][n]; }
终极省内存,一个一维表:
int lcsDP3(char *c1, int m, char *c2, int n) { vector<int> ta(n+1); int t1 = 0; int t2 = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { t2 = ta[j+1]; if (c1[i] == c2[j]) { ta[j+1] = t1+1; } else { ta[j+1] = max(ta[j], t2); } t1 = t2; } t1 = 0; } return ta[n]; }
测试:
int main() { char X[] = "AGGTAB"; char Y[] = "GXTXAYB"; int m = strlen(X); int n = strlen(Y); printf("Length of LCS is %d\n", lcsDP2( X, m, Y, n ) ); system("pause"); return 0; }