Problems involving comparing or matching two sequences (strings/arrays) using 2D DP
This pattern is used when you need to:
- Compare two sequences (strings, arrays)
- Find relationships between two sequences
- Transform one sequence into another
- Find common elements/patterns between sequences
Key Characteristics:
- 2D DP table:
dp[i][j]= answer for firstielements of seq1 and firstjelements of seq2 - Recurrence typically involves: diagonal (match), left, top
- Time: O(m × n), Space: O(m × n) [can optimize to O(min(m, n))]
-
Longest Common Subsequence (LCS) - LeetCode 1143
- Find longest subsequence common to both strings
- File:
longestCommonSubsequence.js(+.d.tstypings)
-
Edit Distance (Levenshtein Distance) - LeetCode 72
- Minimum operations to convert word1 to word2 (insert/delete/replace)
- File:
editDistance.ts
-
Interleaving String - LeetCode 97
- Check if s3 is formed by interleaving s1 and s2
- File:
interleavingString.ts
-
Delete Operation for Two Strings - LeetCode 583
- Minimum deletions to make both strings equal (uses the LCS pattern!)
- File:
deleteOperation.ts
-
Minimum ASCII Delete Sum for Two Strings - LeetCode 712
- Minimum ASCII sum of deleted characters to make strings equal
- Difficulty: Medium ⭐⭐⭐
- Hint: Similar to Delete Operation but with ASCII values
-
Longest Common Substring
- Find longest contiguous common substring
- Difficulty: Medium ⭐⭐
- Note: Different from LCS - must be contiguous!
-
Uncrossed Lines - LeetCode 1035
- Maximum number of uncrossed connecting lines between two arrays
- Difficulty: Medium ⭐⭐⭐
- Hint: This is LCS in disguise!
-
Regular Expression Matching - LeetCode 10
- Match pattern with wildcards (* and .)
- Difficulty: Hard ⭐⭐⭐⭐
- Note: More complex but uses two-sequence DP
-
Wildcard Matching - LeetCode 44
- Match pattern with wildcards (? and *)
- Difficulty: Hard ⭐⭐⭐⭐
-
Distinct Subsequences - LeetCode 115
- Count distinct subsequences of s that equal t
- Difficulty: Hard ⭐⭐⭐⭐
dp[i][j] = answer for:
- First i characters/elements of sequence 1
- First j characters/elements of sequence 2
if (seq1[i-1] === seq2[j-1]) {
dp[i][j] = dp[i-1][j-1] + cost; // Match: use diagonal
} else {
dp[i][j] = min/max(
dp[i-1][j], // Skip from seq1
dp[i][j-1], // Skip from seq2
dp[i-1][j-1] // Replace/transform
);
}dp[i][j] = (dp[i-1][j] && seq1[i-1] === target[k]) ||
(dp[i][j-1] && seq2[j-1] === target[k]);| Problem | DP State | Match Case | No Match Case | Complexity |
|---|---|---|---|---|
| LCS | Length of LCS | dp[i-1][j-1] + 1 |
max(dp[i-1][j], dp[i][j-1]) |
O(m×n) |
| Edit Distance | Min operations | dp[i-1][j-1] |
1 + min(delete, insert, replace) |
O(m×n) |
| Delete Operation | Min deletions | dp[i-1][j-1] |
1 + min(dp[i-1][j], dp[i][j-1]) |
O(m×n) |
| ASCII Delete Sum | Min ASCII sum | dp[i-1][j-1] |
min(ascii + dp[i-1][j], ascii + dp[i][j-1]) |
O(m×n) |
| Interleaving | Can form? | (dp[i-1][j] && match) || (dp[i][j-1] && match) |
false |
O(m×n) |
| Uncrossed Lines | Max lines | dp[i-1][j-1] + 1 |
max(dp[i-1][j], dp[i][j-1]) |
O(m×n) |
- ✅ Longest Common Subsequence
- ✅ Edit Distance
- Longest Common Substring
- Delete Operation for Two Strings
- Minimum ASCII Delete Sum
- Uncrossed Lines
- Interleaving String
- Distinct Subsequences
- Regular Expression Matching
- Wildcard Matching
- LCS is the foundation - Many problems are variations of LCS
- Base cases matter - First row/column initialization is crucial
- Match vs No Match - The recurrence differs based on whether characters match
- Space optimization - Can reduce to O(min(m, n)) by using only previous row
- Reconstruction - Can trace back to find actual solution, not just the value
- 1D DP: Longest Increasing Subsequence (similar but 1D)
- String DP: Palindrome problems, Word Break
- Grid DP: Unique Paths (similar 2D structure)
- NeetCode - Two Sequences DP
- Educative.io - Grokking DP Patterns
- LeetCode: Search "Two Sequences" or "2D DP"
Last Updated: 2024