Problem
Given two strings:
A = CAT
B = CUTFind the minimum number of operations required to convert:
Ainto:
BAllowed operations:
Insert
Delete
ReplaceEach operation has cost:
1Example:
CAT
↓
CUTReplace:
A -> UCost:
1Answer:
1State Design
Define:
edit(i,j)Meaning:
Minimum cost to convert:
A[i..end]
into
B[j..end]Example:
A = CAT
B = CUTedit(1,1)means:
Convert:
"AT"
into
"UT"with minimum cost.
DP State
dp[i][j]stores:
Minimum cost to convert:
A[i..]
into
B[j..]Notice:
dp[i][j]is simply:
edit(i,j)written down in a table.
Match Case
If:
A[i] == B[j]Example:
T
TNo operation is needed.
Therefore:
edit(i,j)
=
edit(i+1,j+1)or:
dp[i][j]
=
dp[i+1][j+1]No additional cost.
Mismatch Case
Example:
A
UThree choices exist.
Replace
Replace:
A -> UCost:
1 + edit(i+1,j+1)Delete
Delete:
ACost:
1 + edit(i+1,j)Insert
Insert:
Ubefore A.
Cost:
1 + edit(i,j+1)Choose the cheapest:
edit(i,j)
=
1 + min(
edit(i+1,j+1),
edit(i+1,j),
edit(i,j+1)
)Recurrence
Match
if A[i] == B[j]
dp[i][j]
=
dp[i+1][j+1]Mismatch
if A[i] != B[j]
dp[i][j]
=
1 + min(
dp[i+1][j+1], // replace
dp[i+1][j], // delete
dp[i][j+1] // insert
)Base Cases
Source String Exhausted
Suppose:
A = ""
B = "ABC"Need:
3 insertsTherefore:
edit(end, j)
=
remaining characters in BTarget String Exhausted
Suppose:
A = "ABC"
B = ""Need:
3 deletesTherefore:
edit(i, end)
=
remaining characters in AExample
edit(1,1)
"AT"
→
"UT"Mismatch:
A != UReplace
AT
→
UTCost:
1Delete
AT
→
T
→
UTCost:
2Insert
AT
→
UAT
→
UTCost:
2Result:
edit(1,1)
=
1Relationship to LCS
State:
lcs(i,j)and
edit(i,j)share the same state space:
(i,j)representing positions in two strings.
LCS
Goal:
maximize matchesMatch:
1 + diagonalMismatch:
max(
down,
right
)Edit Distance
Goal:
minimize operationsMatch:
0 + diagonalMismatch:
1 + min(
diagonal,
down,
right
)Geometry
Like LCS, each state depends on:
right
down
diagonalVisualized as:
j
+---+---+
i | * | R |
+---+---+
i+1 | D | X |
+---+---+Where:
R = dp[i][j+1]
D = dp[i+1][j]
X = dp[i+1][j+1]Important Realization
A DP cell is not a number.
It represents a subproblem.
Example:
dp[1][1]is not:
row 1 column 1It means:
Convert:
"AT"
into
"UT"Every cell in the table is a specific problem instance.
The table merely stores the answers.
Personal Observation
A major DP milestone is realizing:
dp[i][j]is not the state.
The state is:
(i,j)The DP table is only storage.
The true DP design is:
State
Transition
Base CasesThe table is simply a cache of solved subproblems.
Connection to Earlier Lessons
Fibonacci
state = n
House Robber
state = i
Knapsack
state = (item, capacity)
Coin Change
state = amount
LCS
state = (i, j)
Edit Distance
state = (i, j)The state space can stay the same while the optimization objective changes.
This is one of the deepest DP insights learned so far.