Longest Common Substring
Longest Common Substring is a medium dynamic programming problem solved with the strings pattern.
The best approach, optimal (dp ending at each pair, one row), runs in O(m · n) time and O(n) space.
Below are 2 approaches in Java, from brute force up.
Problem
Return the length of the longest common substring (contiguous) of two strings.
Examples
Example 1
- Input
s1 = "ABCDGH", s2 = "ACDGHR"- Output
4- Why
- "CDGH".
Example 2
- Input
s1 = "abc", s2 = "acb"- Output
1
Constraints
1 <= length <= 1000.- Unlike a subsequence, a substring must be contiguous.
Animated walkthrough
A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.
Concepts first, then the problem and every approach, step by step.
Space to play or pause · ← → to jump a step · click or drag the bar to seek
Solutions
Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.
| Approach | Time | Space |
|---|---|---|
| Brute force | O(m · n · min(m, n)) | O(1) |
| Optimal (DP ending at each pair, one row) | O(m · n) | O(n) |
1Brute force
O(m · n · min(m, n))O(1)For every pair of start positions, extend while the characters match.
- For i, j: k = 0; while s1[i + k] == s2[j + k]: k++; track the max.
class Solution {
public int longestCommonSubstr(String s1, String s2) {
int best = 0;
for (int i = 0; i < s1.length(); i++)
for (int j = 0; j < s2.length(); j++) {
int k = 0;
while (i + k < s1.length() && j + k < s2.length() && s1.charAt(i + k) == s2.charAt(j + k)) k++;
best = Math.max(best, k);
}
return best;
}
}2Optimal (DP ending at each pair, one row)
O(m · n)O(n)Match: dp[i][j] = dp[i - 1][j - 1] + 1; mismatch: 0. Track the running maximum. With one row, loop j backwards so dp[j - 1] still holds the previous row's value.
- For i, for j from n down to 1: dp[j] = match ? dp[j - 1] + 1 : 0; best = max.
class Solution {
public int longestCommonSubstr(String s1, String s2) {
int n = s2.length(), best = 0;
int[] dp = new int[n + 1];
for (int i = 1; i <= s1.length(); i++)
for (int j = n; j >= 1; j--) {
dp[j] = s1.charAt(i - 1) == s2.charAt(j - 1) ? dp[j - 1] + 1 : 0;
best = Math.max(best, dp[j]);
}
return best;
}
}Edge cases to test
- No common character (0)
Hints
Hint 1
dp[i][j] = length of the common substring ending exactly at s1[i - 1] and s2[j - 1]. A mismatch resets it to 0. The answer is the maximum cell, not the last one.
FAQ
What is the best time complexity for Longest Common Substring?
Optimal (DP ending at each pair, one row) runs in O(m · n) time and O(n) extra space.
Which pattern does Longest Common Substring use?
It is a dynamic programming problem that uses the strings pattern. Other problems with the same pattern: Edit Distance, Longest Common Subsequence, Longest Palindromic Subsequence.
Is there a brute force solution for Longest Common Substring?
Yes. Brute force takes O(m · n · min(m, n)) time and O(1) space. For every pair of start positions, extend while the characters match.
Which edge cases should I test for Longest Common Substring?
No common character (0).