Longest Common Subsequence
The longest common subsequence of two sequences is the longest ordered (not necessarily contiguous) run of elements they both share — the foundation under diff tools, DNA alignment, and the edit-distance family of problems.
Prerequisites: Memoization vs Tabulation
git diff telling you which lines changed between two file versions, and a bioinformatics tool aligning two DNA strands, are solving the same underlying problem: given two sequences, what is the longest subsequence — elements in the same relative order, but not necessarily adjacent — that both share? That's the longest common subsequence (LCS), and it's the template that the edit-distance family of problems is built on top of.
The idea: a 2D table, one decision per cell
Define as the LCS length using the first characters of string and the first characters of string . Two cases, driven entirely by whether the current characters match:
In words: if the last characters of both prefixes match, they must belong in the LCS together, so take the best answer without them and add one. If they don't match, at least one of the two characters is useless for this particular ending, so take the better of dropping either one. This is time and space for strings of length and — a table with one row per character of and one column per character of .
Worked example: LCS of "ABC" and "AC"
Table rows for = "AC" prefixes 0,1,2, columns for = "ABC" prefixes 0,1,2,3, dp[0][*] = dp[*][0] = 0. : match, . : no match, . : no match, ; need : , no match, ; so . : match, . Final LCS length is 2 ("AC").
def lcs(a, b): # O(m*n) time and space
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
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[m][n]
LCS's whole recurrence collapses to one question per cell: do the current characters match? If yes, extend a diagonal match by one; if no, inherit the best of the neighbor above or to the left. Nearly every string-alignment DP problem is a variation on this single table.
LCS is a subsequence match (order preserved, gaps allowed), not a substring match (contiguous). Confusing the two is the most common mistake — "longest common substring" uses a different, simpler recurrence where a mismatch resets the cell to 0 instead of taking a max.
Where it shows up
Interview staples: longest common subsequence itself, and it's the backbone underneath Edit Distance and shortest common supersequence. On a desk, LCS-style alignment underlies diffing tool implementations, comparing two versions of a strategy's trade log or two related time series for structural similarity, and sequence-alignment tasks borrowed directly from bioinformatics tooling used in some alternative-data pipelines.
Related concepts
Practice in interviews
Further reading
- Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms (ch. 15.4)