The Longest Common Subsequence (LCS) problem is as follows:
Given two sequences s and t, find the length of the longest sequence r, which is a subsequence of both s and t.
Do you know the difference between substring and subequence? Well, substring is a contiguous series of characters while subsequence is not necessarily. For example, "abc" is a both a substring and a subseqeunce of "abcde" while "ade" is only a subsequence.
This problem is a classic application of Dynamic Programming. Let‘s define the sub-problem (state) P[i][j] to be the length of the longest subsequence ends at i of s and j of t. Then the state equations are
- P[i][j] = max(P[i][j - 1], P[i - 1][j]) if s[i] != t[j];
- P[i][j] = P[i - 1][j - 1] + 1 if s[i] == t[j].
This algorithm gives the length of the longest common subsequence. The code is as follows.
1 int longestCommonSubsequence(string s, string t) { 2 int m = s.length(), n = t.length(); 3 vector<vector<int> > dp(m + 1, vector<int> (n + 1, 0)); 4 int maxlen = 0; 5 for (int i = 1; i <= m; i++) { 6 for (int j = 1; j <= n; j++) { 7 dp[i][j] = (s[i - 1] == t[j - 1] ? dp[i - 1][j - 1] + 1 : max(dp[i - 1][j], dp[i][j - 1])); 8 maxlen = max(maxlen, dp[i][j]); 9 } 10 } 11 return maxlen; 12 }
Well, this code has both time and space complexity of O(m*n). Note that when we update dp[i][j], we only need dp[i - 1][j - 1], dp[i - 1][j] and dp[i][j - 1]. We can further optimize it as follows.