Leetcode 1143. Longest Common Subsequence
Table of Contents
Problem Informations
- Problem Index: 1143
- Problem Link: Longest Common Subsequence
- Topics: String, Dynamic Programming
Problem Description
Given two strings text1
and text2
, return the length of their longest common subsequence. If there is no common subsequence, return 0
.
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.
- For example,
"ace"
is a subsequence of"abcde"
.
A common subsequence of two strings is a subsequence that is common to both strings.
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.
Constraints:
text1
andtext2
consist of only lowercase English characters.
Intuition
The problem of finding the longest common subsequence (LCS) between two strings is a classical problem often solved using dynamic programming. The main idea is to break down the problem into smaller subproblems that can be solved recursively. My first thought was to leverage the properties of subsequences and utilize a 2D dynamic programming table to systematically evaluate possible subsequences and store intermediate results. This enables efficient computation by avoiding redundant evaluations.
Approach
The approach uses dynamic programming to find the length of the longest common subsequence between two strings, text1
and text2
. The essence of this approach is to create a 2D array dp
where dp[i][j]
holds the length of the longest common subsequence of substrings text1[0...i-1]
and text2[0...j-1]
.
Initialization: We initialize a 2D array
dp
of size(n+1) x (m+1)
, wheren
is the length oftext1
andm
is the length oftext2
. Each cell is initialized to zero. The extra row and column (beginning with index 0) allow us to handle the base cases effortlessly.Iteration: We iterate through each character in
text1
using an indexi
and each character intext2
using an indexj
. For every pair of characters(text1[i], text2[j])
, we update thedp
table based on the following cases:- If the characters
text1[i]
andtext2[j]
match, it means they can be part of a common subsequence. Hence, we can extend the previous common subsequence found by adding these characters. Therefore,dp[i+1][j+1] = dp[i][j] + 1
. - If the characters do not match, the longest common subsequence up to this point could either exclude
text1[i]
ortext2[j]
. Therefore, we take the maximum value from considering either subproblem,dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j])
.
- If the characters
Result: After filling up the
dp
table, the desired length of the longest common subsequence will be found atdp[n][m]
.
This method runs in time complexity due to the double loop over the characters of both strings and uses space as well, due to the storage requirements of the dp
table. Given the constraints, this is an efficient and feasible approach.
Code
C++
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
// Create a 2D DP array initialized to 0
vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
// Iterate through each character of both strings
for (int i = 0; i < text1.size(); i++) {
for (int j = 0; j < text2.size(); j++) {
// If characters match, increment the length of common subsequence
if (text1[i] == text2[j]) {
dp[i + 1][j + 1] = dp[i][j] + 1;
} else {
// Otherwise, carry forward the maximum length found so far
dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]);
}
}
}
// Return the length of the longest common subsequence
return dp[text1.size()][text2.size()];
}
};
Python
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
# Create a 2D DP array initialized to 0
dp = [[0] * (len(text2) + 1) for _ in range(len(text1) + 1)]
# Iterate through each character of both strings
for i in range(len(text1)):
for j in range(len(text2)):
# If characters match, increment the length of common subsequence
if text1[i] == text2[j]:
dp[i + 1][j + 1] = dp[i][j] + 1
else:
# Otherwise, carry forward the maximum length found so far
dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j])
# Return the length of the longest common subsequence
return dp[len(text1)][len(text2)]
Complexity
Time complexity: The time complexity of the algorithm is , where is the length of
text1
and is the length oftext2
. This is because the algorithm uses a nested loop to iterate through each character in both strings, resulting in iterations.Space complexity: The space complexity of the algorithm is . The algorithm creates a 2D dynamic programming (DP) array
dp
of size to store the lengths of the common subsequences at each point. Thus, the space required is proportional to the product of the lengths of the input strings.
Disclaimer: All reference materials on this website are sourced from the internet and are intended for learning purposes only. If you believe any content infringes upon your rights, please contact me at csnote.cc@gmail.com, and I will remove the relevant content promptly.
Feedback Welcome: If you notice any errors or areas for improvement in the articles, I warmly welcome your feedback and corrections. Your input will help this blog provide better learning resources. This is an ongoing process of learning and improvement, and your suggestions are valuable to me. You can reach me at csnote.cc@gmail.com.