Longest Common Subsequence
Row i only reads row i − 1 and the cell just left of it in row i. So two rows are enough: one for the row above and one being filled. After each letter of text1, the new row becomes the row above. Put the shorter string along the row, so each row is as short as possible.
Filling row by row, from left to right, means each cell reads only finished cells, so dp[i][j] is correct the moment it is written.
Problem
You are given two strings text1 and text2. Find the length of the longest common subsequence: a string you can make from both strings by deleting some letters (or none) and keeping the rest in order. Return that length. If the strings share no letter, return 0.
Two strings, text1 and text2.
The length of the longest string that is a subsequence of both.
ace is in both strings: delete b and d from abcde. No longer string is shared, so the answer is 3.
The whole string is shared.
The strings share no letters.
- • 1 ≤ text1.length, text2.length ≤ 1000
- • Lowercase English letters only.
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
Does a common subsequence need the same position in both strings, or only the same order of letters?
- 2.
If I look at the last letter of each string, what choices do I have for that pair?
- 3.
Do I have to use the last letter of text1? Can I skip it and still have a valid answer?
- 4.
If the last letters match, how does that change the question about the shorter strings?
- 5.
What is the answer when one of the strings is empty?
Brute force approach
Better approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Compare the last letters: a match is used; otherwise drop one and recurse | O(2^(N + M)) | O(N + M) |
| Better | dp[i][j] for every pair of prefixes; each cell is filled once from finished cells | O(N · M) | O(N · M) |
| Optimal | Keep only the row above and the current row; same rule, less memory | O(N · M) | O(min(N, M)) |
Why does this belong to this pattern?
- “subsequence (letters can be skipped, order kept)”Gaps are allowed, so the answer is not a run of neighbours. That makes it LCS, not a substring.
- “common to both strings”Two strings and one answer: compare prefixes of both at once with a table dp[i][j].
- “return the length”We need a count, not the letters, so each cell stores one number.
This question is the anchor of the sub-pattern. The rule is match → 1 + dp[i−1][j−1], and otherwise max(dp[i−1][j], dp[i][j−1]). The later questions in this sub-pattern reuse this table and change one thing. Watch the gap: a subsequence can skip letters, so a mismatch never resets the count to 0, unlike a substring.
Don't make this mistake
The substring rule resets to 0 on a mismatch, because a substring must be one unbroken run. A subsequence can skip letters. On the dry run (abcde and ace), the wrong rule returns 1, but the answer is 3. The letters a, c and e are never next to each other in abcde, so the run resets every time.
In the wrong version, row[j−1] has already been overwritten with this letter's value, so one letter of text1 can be used twice. With text1 = "a" and text2 = "aa", it returns 2, but the answer is 1, because text1 has only one a. Keep the old row in prev and write into cur.
When the letters differ, the answer can come from the cell above or the cell to the left, not just the diagonal. On the dry run, using only the diagonal on a mismatch returns 1, but the answer is 3.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like DP — Strings translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.