How to find Longest Common Substring using C
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
The longest common substring problem asks for the longest contiguous sequence of characters shared by two strings. The word contiguous is the key detail: unlike longest common subsequence, you are not allowed to skip characters in the middle.
Dynamic Programming Idea
The standard solution uses dynamic programming. Let dp[i][j] represent the length of the longest common suffix ending at a[i - 1] and b[j - 1]. If the characters match, you extend the previous diagonal value by one. If they do not match, the current suffix length becomes zero because a substring cannot have gaps.
That gives the recurrence:
- if
a[i - 1] == b[j - 1], thendp[i][j] = dp[i - 1][j - 1] + 1 - otherwise
dp[i][j] = 0
While filling the table, you also track the best length found so far and where it ends in the first string.
A Runnable C Implementation
The following program computes the longest common substring and prints it. It uses dynamic allocation for the table and copies the resulting substring into a newly allocated output buffer.
For these inputs, the output is ana.
Why the Reset to Zero Matters
The zero on mismatch is what makes this a substring algorithm rather than a subsequence algorithm. If you reused a value from the left or top cell on mismatch, you would be allowing gaps, which changes the problem completely.
That is why the table stores common suffix lengths rather than arbitrary best values. Every cell answers a very narrow question: how long is the matching run ending exactly here? Once you think about it that way, the recurrence becomes natural.
Space Optimization
The full table uses O(m * n) time and O(m * n) memory for strings of lengths m and n. For moderate inputs that is fine, but for large strings the memory cost can become significant.
You can reduce memory to O(n) by keeping only the previous row and the current row, because each cell depends only on the diagonal value from the previous row. The logic stays the same, but you store fewer intermediate values.
This version returns only the length, which is often enough when you care about scoring similarity rather than reconstructing the substring itself.
Common Pitfalls
- Confusing longest common substring with longest common subsequence.
- Forgetting to reset the DP cell to zero on mismatch.
- Tracking only the maximum length and not the end position needed to extract the answer.
- Allocating a full matrix for very large strings without considering memory use.
- Forgetting to free the dynamically allocated result or DP buffers.
Summary
- Longest common substring requires consecutive matching characters.
- Dynamic programming solves it cleanly in
O(m * n)time. - Each DP cell stores the length of a matching suffix ending at a specific pair of positions.
- Track both best length and best end index if you need the substring itself.
- Use a rolling-row optimization when memory matters more than reconstructing the full table.
Related reading
- how to find longest palindromic subsequence?
- How to find max. and min. in array using minimum comparisons?
- How to find maximum spanning tree?
- How to find minimum number of jumps to reach the end of the array in On time
- How to find out if an item is present in a stdvector?
- How to find rank of an element in stl set in Ologn
- How to find minimum positive contiguous sub sequence in On time?
- How to find mother vertex in a directed graph in Onm?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.