Coding interview problems › Dynamic Programming
🪙 Dynamic Programming Medium
Longest Common Subsequence
Longest Common Subsequence explained: build the 2D DP table cell by cell, recover the LCS string, O(m·n) tested Python and a live table-filling visual.
Also searched as: LCS dynamic programming · longest common subsequence dp table · LCS of two strings
Try it live Free
2D DP Table: LCS & Edit Distance
Type two strings, pick LCS, and watch the table fill cell by cell with arrows showing which neighbour won, then trace the answer path back out of the grid while the counter compares naive recursion's call count with the m×n cells.
Also useful: Recursion & the Call Stack
The problem
Given two strings, return the length of their longest common subsequence: the longest sequence of characters that appears in both strings in the same order, though not necessarily next to each other.
"ace"
The key insight
Compare the last characters of two prefixes. If they match, that character extends the LCS of both shorter prefixes: dp[i-1][j-1] + 1. If they differ, one of them is not in the answer, so take the better of dropping either: max(dp[i-1][j], dp[i][j-1]). A table of all prefix pairs holds every subproblem exactly once.
Step-by-step approach
- Create a
(m + 1) × (n + 1)table of zeros; row 0 and column 0 represent empty prefixes. - For
iin 1..m andjin 1..n, comparea[i-1]andb[j-1]. - On a match,
dp[i][j] = dp[i-1][j-1] + 1(diagonal). - Otherwise,
dp[i][j] = max(dp[i-1][j], dp[i][j-1])(up or left). - The answer is
dp[m][n]. To recover the string, walk back from that cell following the moves that produced each value.
Python solution
def longest_common_subsequence(a, b):
m, n = len(a), len(b)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if a[i - 1] == b[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1 # diagonal
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) # up or left
return dp[m][n]Complexity
One O(1) computation per cell of the m × n table. Only the previous row is needed for the length, so space can drop to O(min(m, n)).
Common mistakes
- Confusing subsequence with substring. For longest common substring, a mismatch resets the cell to 0 instead of taking a max.
- Indexing the strings with
iandjinstead ofi - 1andj - 1when the table has the extra empty row and column. - Creating the table with
[[0] * (n + 1)] * (m + 1), which makes every row the same list object.
Frequently asked questions
What is the time and space complexity of LCS?
O(m × n) time. The full table is O(m × n) space; if you only need the length, two rows give O(min(m, n)) space.
How do I print the actual longest common subsequence?
Keep the full table and start at dp[m][n]. If the characters match, record it and move diagonally; otherwise move to whichever of up or left holds the larger value. Reverse the collected characters at the end.
What is the difference between LCS and edit distance?
Both fill a table over prefix pairs. LCS maximises matched characters; edit distance minimises insertions, deletions and replacements. With only insertions and deletions allowed, the edit distance equals m + n - 2 × LCS.
Where is LCS used in practice?
Diff tools such as git diff, DNA sequence comparison and plagiarism checks all rely on LCS-style alignment.
Preparing for placements?
Take the 2-minute readiness check to find your weak patterns, then follow the placement path from DSA core to system design.
All coding interview problems More Dynamic Programming Coin Change (DP) lab Placement prep guides
Problem statements on this site are written in our own words. Problem names are the common names used across interview-prep communities; BitBootcamp is an independent learning platform and is not affiliated with LeetCode or any company that asks these questions.