Given two strings text1 and text2, return the length of their longest common subsequence.A subsequence of a string is a new string generated from the original string with some characters(can be none) deleted without changing the relative or
Given two strings text1 and text2, return the length of their longest common subsequence. A subsequence of a string is a new string generated from the original string with some characters(can be none) deleted without changing the relative order of the remaining characters. (eg, "ace" is a subsequence of "abcde" while "aec" is not). A common subsequence of two strings is a subsequence that is common to both strings. If there is no common subsequence, return 0. Example 1: Input: text1 = "abcde", text2 = "ace" Output: 3 Explanation: The longest common subsequence is "ace" and its length is 3. Example 2: Input: text1 = "abc", text2 = "abc" Output: 3 Explanation: The longest common subsequence is "abc" and its length is 3. Example 3: Input: text1 = "abc", text2 = "def" Output: 0 Explanation: There is no such common subsequence, so the result is 0.
DP with a 2D array
Time & space: O(m * n)
1 class Solution { 2 public int longestCommonSubsequence(String text1, String text2) { 3 if (text1 == null || text1.length() == 0 || text2 == null || text2.length() == 0) 4 return 0; 5 int[][] dp = new int[text1.length() + 1][text2.length() + 1]; 6 for (int i = 1; i <= text1.length(); i ++) { 7 for (int j = 1; j <= text2.length(); j ++) { 8 int val = Math.max(dp[i - 1][j], dp[i][j - 1]); 9 if (text1.charAt(i - 1) == text2.charAt(j - 1)) { 10 val = Math.max(val, dp[i - 1][j - 1] + 1); 11 } 12 dp[i][j] = val; 13 } 14 } 15 return dp[text1.length()][text2.length()]; 16 } 17 }
(Skim through) memory optimization, referencing: https://leetcode.com/problems/longest-common-subsequence/discuss/351689/Java-Two-DP-codes-of-O(mn)-and-O(min(m-n))-spaces-w-picture-and-analysis
Obviously, the code in method 1 only needs information of previous row to update current row. So we just use a two-row 2D array to save and update the matching results for chars in s1
and s2
.
Note: use k ^ 1
and k ^= 1
to switch between dp[0] (row 0)
and dp[1] (row 1)
.
1 public int longestCommonSubsequence(String s1, String s2) { 2 int m = s1.length(), n = s2.length(); 3 if (m < n) return longestCommonSubsequence(s2, s1); 4 int[][] dp = new int[2][n + 1]; 5 for (int i = 0, k = 1; i < m; ++i, k ^= 1) 6 for (int j = 0; j < n; ++j) 7 if (s1.charAt(i) == s2.charAt(j)) dp[k][j + 1] = 1 + dp[k ^ 1][j]; 8 else dp[k][j + 1] = Math.max(dp[k ^ 1][j + 1], dp[k][j]); 9 return dp[m % 2][n]; 10 }