Skip to main content
Medium Dynamic Programming High frequency

Longest Common Subsequence

Open on LeetCode

Approach Summary

dp[i][j] = LCS of first i chars of s1 and first j chars of s2. If match: dp[i-1][j-1]+1. Else: max(dp[i-1][j], dp[i][j-1]).

Full Solution & Approach

Define dp[i][j] as the length of the longest common subsequence of text1[0..i) and text2[0..j). If text1[i-1] equals text2[j-1], that character extends the LCS, so dp[i][j] = dp[i-1][j-1] + 1. If they differ, the best we can do is skip one of them: dp[i][j] = max(dp[i-1][j], dp[i][j-1]). Base cases are the zero row and column — an empty prefix has LCS length 0. Fill the table row by row; the answer is dp[m][n]. The recurrence is the definition of LCS and is the foundation for edit distance and other string DP problems. Space can be reduced to two rolling rows since each cell only reads the current and previous rows, but the full table is the clearest starting point.

Every cell of the m × n table is computed once — O(m × n) time. The full table costs O(m × n) space, reducible to O(min(m, n)) with a rolling row.

Solution Code

Solution

def longest_common_subsequence(text1: str, text2: str) -> int:
    m, n = len(text1), len(text2)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if text1[i - 1] == text2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1
            else:
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
    return dp[m][n]

Edge Cases to Watch

  • One string empty — LCS is 0
  • Identical strings — the LCS is the whole string
  • No shared characters — 0
  • Repeated characters — the DP handles counts correctly

How to Recognize This Pattern

  • LCS of two sequences
  • 2D DP table

Complexity Analysis

Time Complexity

O(m × n)

Space Complexity

O(m × n)

Tags

String DP

This site is free. If these guides are helping your prep, consider buying me a coffee. ☕

Support →
Buy me a coffee