codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🧮

Data Structures & Algorithms

30 / 65 topics
27Dynamic Programming Basics28Fibonacci Sequence using DP29Knapsack Problem30Longest Common Subsequence (LCS)31Edit Distance
Tutorials/Data Structures & Algorithms/Longest Common Subsequence (LCS)
🧮Data Structures & Algorithms

Longest Common Subsequence (LCS)

Updated 2026-04-20
4 min read

Introduction

The Longest Common Subsequence (LCS) problem is a classic algorithmic challenge that involves finding the longest subsequence common to two sequences. A subsequence is defined as a sequence derived from another sequence where some elements may be deleted without changing the order of the remaining elements.

This tutorial will guide you through understanding the LCS problem, its applications, and how to solve it using dynamic programming. We'll cover both the recursive and iterative approaches, along with code examples in Python.

Problem Statement

Given two sequences X and Y, find the length of their longest common subsequence.

Example

Consider the sequences:

  • X = "ABCBDAB"
  • Y = "BDCAB"

The longest common subsequence is "BCAB", which has a length of 4.

Dynamic Programming Approach

Dynamic programming (DP) is an efficient method for solving optimization problems by breaking them down into simpler subproblems and storing the results of these subproblems to avoid redundant calculations.

Steps to Solve LCS using DP

  1. Define the Subproblem: Let dp[i][j] represent the length of the longest common subsequence of the first i characters of sequence X and the first j characters of sequence Y.

  2. Recurrence Relation:

    • If X[i-1] == Y[j-1], then dp[i][j] = dp[i-1][j-1] + 1.
    • Otherwise, dp[i][j] = max(dp[i-1][j], dp[i][j-1]).
  3. Base Case:

    • If either sequence is empty (i == 0 or j == 0), then dp[i][j] = 0.
  4. Compute the DP Table: Fill the table using the recurrence relation.

  5. Reconstruct the LCS (Optional): Trace back through the DP table to find the actual subsequence.

Code Example

Here's a Python implementation of the LCS problem using dynamic programming:

def lcs(X, Y):
    m = len(X)
    n = len(Y)
    
    # Create a 2D array to store lengths of longest common subsequence.
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    
    # Build the dp array from bottom up
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if X[i - 1] == Y[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1
            else:
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
    
    # The length of the longest common subsequence is in dp[m][n]
    return dp[m][n]

# Example usage
X = "ABCBDAB"
Y = "BDCAB"
print("Length of LCS:", lcs(X, Y))

Explanation

  • Initialization: We initialize a 2D list dp with dimensions (m+1) x (n+1) where m and n are the lengths of sequences X and Y, respectively. Each element is initialized to 0.

  • Filling the DP Table: We iterate through each character of both sequences. If characters match, we increment the value from the diagonal cell (dp[i-1][j-1] + 1). If they don't match, we take the maximum value from either the left or top cell (max(dp[i-1][j], dp[i][j-1])).

  • Result: The length of the longest common subsequence is found in dp[m][n].

Recursive Approach

While the DP approach is more efficient, a recursive solution can be useful for understanding the problem and for small inputs.

Code Example

Here's a Python implementation using recursion:

def lcs_recursive(X, Y, m, n):
    # Base case: if either string is empty
    if m == 0 or n == 0:
        return 0
    
    # If last characters of both strings match
    if X[m - 1] == Y[n - 1]:
        return 1 + lcs_recursive(X, Y, m - 1, n - 1)
    
    # If last characters do not match
    else:
        return max(lcs_recursive(X, Y, m, n - 1), lcs_recursive(X, Y, m - 1, n))

# Example usage
X = "ABCBDAB"
Y = "BDCAB"
print("Length of LCS:", lcs_recursive(X, Y, len(X), len(Y)))

Explanation

  • Base Case: If either sequence is empty (m == 0 or n == 0), the LCS length is 0.

  • Recursive Case:

    • If the last characters of both sequences match, we include this character in the LCS and move to the previous characters (1 + lcs_recursive(X, Y, m - 1, n - 1)).
    • If they don't match, we take the maximum LCS length by either excluding the current character from X or Y.

Time and Space Complexity

  • Time Complexity: The dynamic programming approach has a time complexity of \(O(m \times n)\), where \(m\) and \(n\) are the lengths of the two sequences.

  • Space Complexity: The space complexity is also \(O(m \times n)\) due to the 2D DP table.

Best Practices

  1. Memoization for Recursive Approach: To optimize the recursive approach, use memoization to store results of subproblems and avoid redundant calculations.

  2. Optimize Space Usage: In the DP approach, you can optimize space by using only two rows at a time instead of the entire 2D table, reducing space complexity to \(O(n)\).

  3. Edge Cases: Handle edge cases where one or both sequences are empty.

  4. Reconstruction: If reconstructing the LCS is required, maintain an additional array to track the direction of traversal in the DP table.

Conclusion

The Longest Common Subsequence problem is a fundamental example of dynamic programming. It has numerous applications in fields such as bioinformatics (for DNA sequence alignment) and text comparison tools. Understanding both the recursive and iterative approaches provides a solid foundation for tackling more complex problems in data structures and algorithms.

By following this tutorial, you should now have a comprehensive understanding of how to solve the LCS problem using dynamic programming, including code examples and best practices.


PreviousKnapsack ProblemNext Edit Distance

Recommended Gear

Knapsack ProblemEdit Distance