String Pattern Matching Naive in DSA C# - Time & Space Complexity
We want to understand how long it takes to find a pattern inside a text using a simple method.
How does the time needed grow when the text or pattern gets bigger?
Analyze the time complexity of the following code snippet.
public static int NaivePatternMatch(string text, string pattern)
{
int n = text.Length;
int m = pattern.Length;
for (int i = 0; i <= n - m; i++)
{
int j;
for (j = 0; j < m; j++)
{
if (text[i + j] != pattern[j])
break;
}
if (j == m)
return i; // pattern found at index i
}
return -1; // pattern not found
}
This code checks every possible position in the text to see if the pattern matches starting there.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Comparing characters of the pattern with the text.
- How many times: For each position in the text (about n - m + 1 times), it compares up to m characters.
As the text and pattern get longer, the number of comparisons grows roughly by multiplying their lengths.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 (text), 3 (pattern) | About 8 * 3 = 24 comparisons |
| 100 (text), 5 (pattern) | About 96 * 5 = 480 comparisons |
| 1000 (text), 10 (pattern) | About 991 * 10 = 9,910 comparisons |
Pattern observation: Doubling the text or pattern length roughly doubles the work, so the total work grows like the product of their sizes.
Time Complexity: O(n * m)
This means the time needed grows proportionally to the text length times the pattern length.
[X] Wrong: "The search always takes time proportional to the text length only."
[OK] Correct: Because for each position in the text, the pattern characters are also checked, so the pattern length matters too.
Understanding this simple search method helps build a foundation for more efficient algorithms and shows you can analyze how code scales with input size.
"What if we used a more advanced algorithm like KMP instead of naive search? How would the time complexity change?"
Practice
Solution
Step 1: Understand naive matching approach
The naive algorithm tries to match the pattern starting at every position in the text.Step 2: Compare with other methods
Other methods like hashing or prefix tables are not used in naive matching.Final Answer:
Check every possible position in the text to find the pattern -> Option AQuick Check:
Naive = Check all positions [OK]
- Confusing naive with hashing or prefix methods
- Thinking naive skips positions
- Assuming sorting is involved
text length is n and pattern length is m?Solution
Step 1: Determine loop range for pattern matching
The loop must run from 0 to n - m inclusive to avoid overflow when matching pattern of length m.Step 2: Check each option
for (int i = 0; i <= n - m; i++) correctly uses i <= n - m. Others either go beyond or are too short.Final Answer:
for (int i = 0; i <= n - m; i++) -> Option DQuick Check:
Loop till n - m inclusive [OK]
- Looping till n causes index out of range
- Looping till m is too short
- Using < instead of <= misses last position
string text = "abcabcabc";
string pattern = "abc";
int count = 0;
for (int i = 0; i <= text.Length - pattern.Length; i++) {
int j;
for (j = 0; j < pattern.Length; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == pattern.Length)
count++;
}
Console.WriteLine(count);Solution
Step 1: Identify pattern occurrences in text
The pattern "abc" appears at positions 0, 3, and 6 in the text "abcabcabc".Step 2: Count matches in the loop
The inner loop confirms full matches at these positions, so count increments 3 times.Final Answer:
3 -> Option CQuick Check:
Pattern occurs 3 times [OK]
- Counting partial matches
- Off-by-one errors in loop limits
- Breaking early without counting
string text = "hellohello";
string pattern = "lo";
int count = 0;
for (int i = 0; i < text.Length - pattern.Length; i++) {
int j;
for (j = 0; j < pattern.Length; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == pattern.Length)
count++;
}
Console.WriteLine(count);Solution
Step 1: Analyze loop boundary
The outer loop runs from 0 to text.Length - pattern.Length - 1, missing the last valid start position.Step 2: Correct loop condition
Changing < to <= ensures the last possible position is checked for pattern match.Final Answer:
The outer loop should use <= instead of < to include last position -> Option AQuick Check:
Loop boundary off by one [OK]
- Using < causes missing last match
- Changing inner loop start breaks matching
- Ignoring initialization of count
"ababababab" and a pattern "abab", how many times will the naive pattern matching algorithm find the pattern if overlapping matches are counted?Solution
Step 1: Identify all overlapping matches
The pattern "abab" appears starting at indices 0, 2, 4, and 6 in the text "ababababab".Step 2: Count total matches including overlaps
Counting all these positions gives 4 matches.Final Answer:
4 -> Option BQuick Check:
Overlapping matches counted = 4 [OK]
- Ignoring overlapping matches
- Counting only non-overlapping occurrences
- Miscounting start indices
Ready to prove it?
Pass the test and this pattern moves unknown
