DP problems — edit distance (Levenshtein)
WHAT is it?
We define a 2D table:
So is our final answer, and (two empty strings cost nothing).
WHY does a recurrence even exist?
The last move is one of:
- Characters match (
A[i-1] == B[j-1]): no edit needed for this position → cost passes through from . - Substitute
A[i-1]→B[j-1]: cost the cost of aligning the smaller prefixes . - Delete
A[i-1](it's an extra char inA): cost . - Insert
B[j-1](it's needed inB): cost .
We take the minimum because we want the cheapest way.
HOW to derive the recurrence from scratch
Why this is correct: every conversion ends with exactly one of the four cases above, each reduces to a strictly smaller subproblem, and we minimise — so we never miss the optimum (this is optimal substructure + overlapping subproblems).

Complexity (the 80/20 takeaway)
- Time: — we fill each cell once in .
- Space: for the full table, or if you only keep the previous row (you only ever read row and column ).
Worked Example 1 — "horse" → "ros" (answer = 3)
We fill the table row by row. Let horse (rows), ros (cols).
| "" | r | o | s | ||
|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | ||
| h | 1 | 1 | 1 | 2 | 3 |
| o | 2 | 2 | 2 | 1 | 2 |
| r | 3 | 3 | 2 | 2 | 2 |
| s | 4 | 4 | 3 | 3 | 2 |
| e | 5 | 5 | 4 | 4 | 3 |
- Why ?
A[1]='o',B[1]='o'match, so we copy the diagonal . Why this step? Matching costs nothing, so the cost equals fixing the smaller prefixes"h"→"r". - Why ?
'e' ≠ 's', so . Why this step? Cheapest predecessor is the delete path (deletee), giving the final 3. - Reading edits back: substitute
h→r? No — actual optimal path is delete h, delete r, substitute e→s (3 edits), matching .
Worked Example 2 — "sunday" → "saturday" (answer = 3)
Key cells:
- The shared
s...n...daystructure means many matches pass straight down the diagonal. - We need to insert
aandt, and substituten→r. That's .
Why this is 3 and not more? Because the long common subsequence
s..dayaligns for free; only 3 positions actually differ in a way that needs work. Why this step matters: edit distance secretly rewards long shared subsequences.
Worked Example 3 — Forecast-then-Verify
Common Mistakes
Recall Feynman: explain to a 12-year-old
Imagine you have two words written on Lego strips and you want to make the first word look exactly like the second. You're allowed three moves: stick on a new letter brick, pull off a letter brick, or swap one brick for another — each move costs one coin. Edit distance is the fewest coins you can spend. The clever trick: instead of solving the whole word at once, you make a little grid and figure out the cheapest fix for the tiny beginnings first (just one letter, then two...), writing each answer in a box. Each new box just peeks at three boxes you already filled (up, left, and up-left) and picks the cheapest one. By the time you reach the bottom-right box, the answer is sitting right there!
Active Recall
What does represent in edit distance?
What are the three allowed operations and their costs?
What is and why?
B[0..j) from an empty string.What is and why?
A[0..i) to empty.When A[i-1] == B[j-1], what is ?
When characters differ, write the transition.
Which neighbour corresponds to a deletion from A?
Which neighbour corresponds to an insertion into A?
Time and space complexity?
Why does the recurrence only look at the last character?
Edit distance of "horse" → "ros"?
Is edit distance equal to length difference?
Connections
- Dynamic Programming — edit distance is a canonical 2D-table DP.
- Longest Common Subsequence — closely related; LCS aligns matches, edit distance counts mismatches.
- Optimal Substructure — the property that makes the recurrence valid.
- Overlapping Subproblems — why memoisation/tabulation beats naive recursion.
- Recursion and Memoization — top-down alternative to the bottom-up table.
- Sequence Alignment — bioinformatics generalisation (Needleman–Wunsch) with weighted costs.
- Space Optimization in DP — the rolling-row trick to reach space.
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Edit distance ka matlab simple hai: do strings di hui hain, aur humein batana hai ki pehli string ko doosri banane ke liye kam se kam kitne single-character edits chahiye. Edits sirf teen type ke allowed hain — ek letter insert karo, ek letter delete karo, ya ek letter ko doosre se substitute (replace) karo. Har edit ka cost 1 hai. Jaise "horse" ko "ros" banane mein 3 edits lagte hain.
Ab DP wala jugaad: hum poori string ek saath solve nahi karte. Hum ek grid (table) banate hain jahan dp[i][j] ka matlab hai "A ke pehle i letters ko B ke pehle j letters banane ka minimum cost". Sabse pehle base cases bharo — agar ek string khaali hai toh saare letters insert ya delete karne padenge, isliye dp[0][j]=j aur dp[i][0]=i. Phir har cell teen padosi cells dekhta hai: diagonal (up-left) substitute/match ke liye, upar wala delete ke liye, aur left wala insert ke liye. Agar current letters match karte hain toh diagonal ko bina +1 ke copy kar lo (free hai!), warna 1 + min(teen padosi).
Yeh kyu important hai? Spell-checkers, DNA sequence matching, "did you mean..." search suggestions, aur diff tools — sab isi idea pe chalte hain. Interview mein bhi yeh classic 2D-DP question hai. Time complexity hai aur thoda smart bano toh space sirf ek row mein ho jaata hai.
Ek common galti yaad rakho: indexing mein gadbad. dp[i][j] mein current characters A[i-1] aur B[j-1] hote hain, A[i] nahi — kyunki i ka matlab "pehle i letters" hai. Aur jab letters match karein tab +1 mat lagana, sirf diagonal copy karna.