पाठ 24 / 26
Two-Dimensional DP
Two sequences, one table.
dp[i][j] over prefixes
Problems over two strings or a grid use a 2-D state: dp[i][j] is the answer for the first i characters of a and the first j of b. Edit distance takes the minimum of insert, delete or replace when characters differ; longest common subsequence extends a match diagonally or takes the better of skipping a character. Because each row depends only on the previous one, memory can drop from O(m·n) to O(n).
Edit distance and LCS, run
I ran this with Python 3.12.3 (standard library only). horse to ros needs 3 edits and intention to execution needs 5; abcde and ace share a subsequence of length 3, while abc and def share none.
# 2-D dynamic programming: edit distance and longest common subsequence
def edit_distance(a, b):
dp = [[0] * (len(b) + 1) for _ in range(len(a) + 1)]
for i in range(len(a) + 1):
dp[i][0] = i
for j in range(len(b) + 1):
dp[0][j] = j
for i in range(1, len(a) + 1):
for j in range(1, len(b) + 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], dp[i][j - 1], dp[i - 1][j - 1])
return dp[-1][-1]
def lcs(a, b):
prev = [0] * (len(b) + 1) # rolling row: O(len(b)) memory
for ch in a:
cur = [0]
for j, bj in enumerate(b, 1):
cur.append(prev[j - 1] + 1 if ch == bj else max(prev[j], cur[j - 1]))
prev = cur
return prev[-1]
print(edit_distance("horse", "ros"), edit_distance("intention", "execution"))
print(lcs("abcde", "ace"), lcs("abc", "def"))
Output:
3 5 3 0
Draw a small table
Filling a 3 by 4 table by hand on the whiteboard makes the transition clear to you and the interviewer.
त्वरित जाँच: What does dp[i][j] mean in edit distance?
- The length of a
- The number of matching characters
- The minimum edits to turn the first i characters of a into the first j of b
- The index of the first mismatch
Answer
The minimum edits to turn the first i characters of a into the first j of b — Answers for prefixes.