LCS & edit distance
In one line
Two-sequence DP fills a table where dp[i][j] answers the question for the first i characters of one string and the first j of the other, comparing the last characters at each step.
What it is
The longest common subsequence (LCS) of two strings is the longest sequence of characters that appears in both in the same order, not necessarily contiguously. For 'abcde' and 'ace' it is 'ace', length 3.
Edit distance (Levenshtein distance) is the minimum number of single-character inserts, deletes and replacements to turn one string into another. 'horse' to 'ros' needs 3: replace h with r, delete r, delete e.
Both use the same table shape: (m + 1) x (n + 1), where row 0 and column 0 represent empty prefixes. Each cell looks at whether the last characters a[i-1] and b[j-1] match and then at three neighbours: up, left and diagonal.
Why interviewers ask
These are the canonical 2D DP problems and appear often in interviews, directly or disguised (minimum deletions to make strings equal, shortest common supersequence, longest palindromic subsequence). Interviewers look for correct base cases, a clear meaning of each neighbour (insert, delete, replace), and the space optimisation to two rows.
How it works
- 1Define dp[i][j] over prefixes: a[:i] and b[:j]. Size (m + 1) x (n + 1).
- 2LCS base: row 0 and column 0 are 0 (an empty string has nothing in common). Edit distance base: dp[i][0] = i (delete everything), dp[0][j] = j (insert everything).
- 3LCS transition: if a[i-1] == b[j-1], dp[i][j] = dp[i-1][j-1] + 1; otherwise dp[i][j] = max(dp[i-1][j], dp[i][j-1]).
- 4Edit distance transition: if the characters match, dp[i][j] = dp[i-1][j-1]; otherwise 1 + min(dp[i-1][j] (delete from a), dp[i][j-1] (insert into a), dp[i-1][j-1] (replace)).
- 5Fill row by row; the answer is dp[m][n]. To reconstruct the subsequence or the edit script, walk back from (m, n) following the choice made at each cell.
- 6Each row only needs the previous row, so space can drop to O(min(m, n)) when you only need the number.
Worked example · Edit distance 'horse' to 'ros', and LCS of 'abcde' and 'ace'
- Edit distance table, columns '', r, o, s. Row '' is [0, 1, 2, 3].
- Row 'h': [1, 1, 2, 3]. h vs r differ: 1 + min(0, 1, 1) = 1 (replace h with r).
- Row 'ho': [2, 2, 1, 2]. o matches o, so dp = diagonal value 1.
- Row 'hor': [3, 2, 2, 2]. Row 'hors': [4, 3, 3, 2], because s matches s and takes the diagonal 2.
- Row 'horse': [5, 4, 4, 3]. Answer dp[5][3] = 3: replace h with r, delete r, delete e.
- LCS of 'abcde' and 'ace': the last row of the table is [0, 1, 2, 3]. Matches at a, c and e each add 1 from the diagonal, giving length 3 ('ace').
Picture it
Comparing two drafts of an essay line by line: at each point you either see the same line in both (keep it and move on in both drafts) or decide whether the difference is best explained by a line added, a line removed or a line rewritten, always picking the explanation that needs the fewest changes overall.
Reference code
def lcs(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
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
return dp[m][n]
def edit_distance(a, b):
m, n = len(a), len(b)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(m + 1):
dp[i][0] = i # delete all of a[:i]
for j in range(n + 1):
dp[0][j] = j # insert all of b[:j]
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]
else:
dp[i][j] = 1 + min(dp[i - 1][j], # delete
dp[i][j - 1], # insert
dp[i - 1][j - 1]) # replace
return dp[m][n]
# lcs("abcde", "ace") -> 3
# edit_distance("horse", "ros") -> 3
Both fill an (m + 1) x (n + 1) table of prefixes in O(m x n) time. Keeping only two rows reduces space to O(n) when you only need the value, not the alignment.
Key patterns
LCS family
When: Common subsequence, minimum deletions to make strings equal, shortest common supersequence
How: Compute LCS; min deletions = m + n - 2 x LCS; shortest supersequence length = m + n - LCS.
Edit distance family
When: Minimum operations between strings, one-edit-away checks
How: Insert/delete/replace table; for 'one edit away' a linear two-pointer check is enough.
Longest palindromic subsequence
When: Longest subsequence that reads the same both ways
How: LCS of the string and its reverse, or interval DP dp[i][j] over the substring.
Longest common substring (contiguous)
When: Characters must be consecutive
How: dp[i][j] = dp[i-1][j-1] + 1 on match, else 0; take the max cell. Different from LCS.
Wildcard and regex matching
When: Pattern with ? * or . *
How: Same 2D prefix table with booleans; * looks at the left or up cell depending on whether it matches zero or more characters.
Real-world use
diff and version control
Unix diff and git show changes between files as a set of inserted and deleted lines, which is an LCS / shortest edit script over lines; git's default is the Myers algorithm, and patience diff anchors on unique common lines.
Spell checking and fuzzy search
Spell checkers suggest dictionary words within a small Levenshtein distance, and Elasticsearch fuzzy queries match terms within an edit distance of 1 or 2 (using Damerau-Levenshtein, which also counts swaps).
Bioinformatics
Aligning DNA or protein sequences uses Needleman-Wunsch (global) and Smith-Waterman (local) alignment, which are edit-distance style tables with scores for matches, mismatches and gaps.
Speech and OCR evaluation
Word error rate in speech recognition and character error rate in OCR are edit distances between the system's output and the reference transcript, divided by the reference length.
In a project
A customer support platform receives many tickets with misspelled product names ('iphnoe 15', 'galxy s24') and wants to map each to the right product from a catalogue of 2,000 names.
- Normalise text (lower case, strip punctuation) and compute edit distance between the typed name and catalogue names.
- Speed it up: only compare against names whose length differs by at most 2, and stop a row early when every value in it exceeds the threshold (banded DP).
- Accept matches with distance at most 2, or at most 20 percent of the length, and send ambiguous ties to a human.
- Measure accuracy on a labelled sample of past tickets and tune the threshold.
Impact: Most tickets are routed to the right product team automatically, cutting manual triage time, and the banded DP keeps matching fast enough to run as each ticket arrives.
Trade-offs
Use it when
- Comparing two sequences: strings, lines of files, DNA
- You need the minimum edits, the longest common part, or an alignment
- m x n is manageable (for example up to about 10^7 cells)
Avoid it when
- Strings are very long and similar: Myers' O((m + n) x D) algorithm or banded DP is far faster
- You only need 'is it one edit away': a linear scan suffices
- Matching against a huge dictionary: use a trie or BK-tree to avoid comparing with every word
Cost: O(m x n) time; O(m x n) space with the full table (needed to reconstruct), O(min(m, n)) with two rows.
Common mistakes
- Confusing subsequence (gaps allowed) with substring (contiguous).
- Wrong edit distance base cases: dp[i][0] = i and dp[0][j] = j, not 0.
- Off-by-one indexing: dp[i][j] compares a[i-1] and b[j-1].
- Mixing up which neighbour is insert and which is delete when explaining or reconstructing the script.
- Overwriting the diagonal value too early in the two-row or one-row optimisation.
Interview questions
Quick revision
- Table (m + 1) x (n + 1) over prefixes; compare a[i-1], b[j-1].
- LCS: match = diag + 1, else max(up, left).
- Edit: base i and j; match = diag, else 1 + min(up, left, diag).
- Up = delete, left = insert, diag = replace.
- edit('horse', 'ros') = 3; LCS('abcde', 'ace') = 3.
- Min deletions = m + n - 2 x LCS.
- O(m x n) time; two rows for O(n) space.
Check yourself
1. What is the LCS length of 'abcde' and 'ace'?
2. What is the edit distance between 'horse' and 'ros'?
3. In edit distance, what are dp[i][0] and dp[0][j]?
4. Two strings have lengths 6 and 4 and an LCS of 3. How many deletions in total make them equal?
Saved on this device. Create a free account to keep it on every device.
Practise this with Sam
A real mock interview, out loud, with an honest scorecard. Free to start.