Longest Common Substring in DSA C - Time & Space Complexity
We want to understand how the time needed to find the longest common substring grows as the input strings get longer.
Specifically, how does the work change when the strings increase in size?
Analyze the time complexity of the following code snippet.
int longestCommonSubstring(char *s1, char *s2) {
int m = strlen(s1);
int n = strlen(s2);
int maxLen = 0;
int dp[m+1][n+1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 || j == 0) dp[i][j] = 0;
else if (s1[i-1] == s2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
if (dp[i][j] > maxLen) maxLen = dp[i][j];
} else {
dp[i][j] = 0;
}
}
}
return maxLen;
}
This code finds the length of the longest substring common to both input strings using a 2D table.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Nested loops over both strings filling the dp table.
- How many times: The inner code runs (m+1) * (n+1) times, where m and n are string lengths.
As the strings get longer, the number of operations grows roughly by multiplying their lengths.
| Input Size (m and n) | Approx. Operations |
|---|---|
| 10 | ~100 |
| 100 | ~10,000 |
| 1000 | ~1,000,000 |
Pattern observation: Doubling the length roughly quadruples the work, showing a multiplication effect.
Time Complexity: O(m * n)
This means the time needed grows proportionally to the product of the two string lengths.
[X] Wrong: "The algorithm only depends on the length of one string, so it is O(n)."
[OK] Correct: The algorithm compares every character of one string with every character of the other, so both lengths matter and multiply the work.
Understanding this time complexity helps you explain how dynamic programming solves problems efficiently by breaking them into smaller parts.
"What if we only compared substrings starting at the same index in both strings? How would the time complexity change?"
Practice
s1 and s2?Solution
Step 1: Understand the problem definition
The Longest Common Substring problem looks for the longest sequence of characters that appear in both strings without any breaks (consecutively).Step 2: Differentiate from similar problems
Unlike Longest Common Subsequence, which allows characters to be non-consecutive, Longest Common Substring requires consecutive matching characters.Final Answer:
The longest sequence of characters that appear consecutively in both strings -> Option AQuick Check:
Longest Common Substring = consecutive matching characters [OK]
- Confusing substring with subsequence
- Thinking characters can be non-consecutive
- Counting total common characters instead of longest consecutive
dp of size m+1 by n+1 with all zeros for Longest Common Substring?Solution
Step 1: Understand array initialization in C
To initialize a 2D array with zeros, we can declare it and then usememsetto set all bytes to zero.Step 2: Analyze each option
int dp[m+1][n+1] = {0}; tries to initialize with {0} but this only works for fixed size arrays, not variable sizes. int dp[m+1][n+1]; memset(dp, 0, sizeof(dp)); declares and usesmemsetcorrectly. int dp[m][n]; for(int i=0;iFinal Answer:
int dp[m+1][n+1]; memset(dp, 0, sizeof(dp)); -> Option BQuick Check:
Use memset to zero initialize arrays in C [OK]
- Using {0} for variable size arrays
- Initializing with wrong values like 1 or -1
- Not initializing dp array before use
s1 = "abcde" and s2 = "abfde"?
int longestCommonSubstring(char* s1, char* s2) {
int m = strlen(s1), n = strlen(s2);
int dp[m+1][n+1];
memset(dp, 0, sizeof(dp));
int maxLen = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1[i-1] == s2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
if (dp[i][j] > maxLen) maxLen = dp[i][j];
} else {
dp[i][j] = 0;
}
}
}
return maxLen;
}
int main() {
printf("%d", longestCommonSubstring("abcde", "abfde"));
return 0;
}Solution
Step 1: Trace matching characters between s1 and s2
Strings: s1 = "abcde", s2 = "abfde". Matching consecutive characters are "ab" at start and "de" at end. "ab" length = 2, "de" length = 2. The longest common substring length is 2.Step 2: Check dp updates for longest substring
At i=3, j=3, characters differ ('c' vs 'f'), so dp resets. The longest substring is "ab" or "de" with length 2.Final Answer:
2 -> Option AQuick Check:
Longest Common Substring length = 2 [OK]
- Counting non-consecutive matches
- Confusing substring length with subsequence length
- Off-by-one errors in indexing
int longestCommonSubstring(char* s1, char* s2) {
int m = strlen(s1), n = strlen(s2);
int dp[m][n];
int maxLen = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (s1[i] == s2[j]) {
dp[i][j] = dp[i-1][j-1] + 1;
if (dp[i][j] > maxLen) maxLen = dp[i][j];
} else {
dp[i][j] = 0;
}
}
}
return maxLen;
}Solution
Step 1: Analyze dp array size and indexing
The dp array is declared as dp[m][n], but the code accesses dp[i-1][j-1] which can cause out-of-bound access when i=0 or j=0.Step 2: Correct dp array size and indexing
To safely access dp[i-1][j-1], dp should be sized (m+1) x (n+1) and loops should run from 1 to m and 1 to n, with dp[0][*] and dp[*][0] initialized to 0.Final Answer:
dp array size should be (m+1) x (n+1) to avoid out-of-bound access -> Option DQuick Check:
Use dp size (m+1)x(n+1) for safe indexing [OK]
- Using dp size m x n causing index errors
- Starting loops at 0 but accessing dp[i-1][j-1]
- Not initializing dp array elements
s1 = "banana" and s2 = "ananas", write a C function to find the longest common substring and return its length. What is the length of the longest common substring?Solution
Step 1: Identify common substrings between s1 and s2
Check substrings of s1 and s2. Common substrings include "ana", "nan", "ana" again, and the longest is "ana" with length 3.Step 2: Confirm no longer substring exists
No substring longer than 3 exists in both strings consecutively. "anana" is not a substring of "banana" starting at index 1 (it's "anana" in s2 but not in s1 consecutively).Final Answer:
3 -> Option CQuick Check:
Longest common substring between "banana" and "ananas" is "ana" length 3 [OK]
- Confusing substring with subsequence
- Assuming "anana" is common substring
- Stopping at shorter matches like "an"
Ready to prove it?
Pass the test and this pattern moves unknown
