03
Common substring (DP — Strings Sub-pattern)
Like LCS, but the common part must be contiguous: dp[i][j] is the length of the common run ending exactly at a[i − 1] and b[j − 1].
Signals in the problem statement
- ›
"longest common substring"
- ›
"maximum length of repeated subarray"
- ›
"contiguous" in a two-string question
What makes it different
Mismatch → 0, not max(top, left). The answer is the largest cell, wherever it is.
Questions
ordered from “learn the idea” to “recognise it without help”- 1Longest Common SubstringWalkthroughMediumBasic Anchor·GeeksforGeeks
- 2Maximum Length of Repeated SubarrayWalkthroughMediumBasic Reinforcement·LeetCode #718
Template
common-substring-template.cpp
// Longest common substring: dp[j] = length of the common run ending at a[i - 1] and b[j - 1].
// A mismatch breaks the run (0). j goes high -> low so dp[j - 1] is still the previous row.
int longestCommonSubstring(const string& a, const string& b) {
int m = b.size(), best = 0;
vector<int> dp(m + 1, 0);
for (size_t i = 1; i <= a.size(); i++)
for (int j = m; j >= 1; j--) {
dp[j] = a[i - 1] == b[j - 1] ? dp[j - 1] + 1 : 0;
best = max(best, dp[j]); // the answer can end anywhere
}
return best;
}Remember this · DP — Strings
Trigger
Longest common subsequence, edit distance, palindromes, matching with wildcards, interleaving.
Think
Look at the last characters: if they match, what do I do? If not, what are my options?
Key question
What does dp[i][j] mean, and what are the empty-string base cases?