String Pattern Matching Naive in DSA Go - Time & Space Complexity
We want to understand how the time needed to find a pattern in a text grows as the text and pattern get bigger.
How does the number of checks change when the text or pattern length increases?
Analyze the time complexity of the following code snippet.
func naivePatternSearch(text, pattern string) []int {
var result []int
n := len(text)
m := len(pattern)
for i := 0; i <= n-m; i++ {
j := 0
for j < m && text[i+j] == pattern[j] {
j++
}
if j == m {
result = append(result, i)
}
}
return result
}
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 characters in 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 character 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: The work grows roughly by the product of text length and pattern length.
Time Complexity: O(n * m)
This means the time needed grows proportionally to the length of the text times the length of the pattern.
[X] Wrong: "The search always takes time proportional only to the text length (O(n))."
[OK] Correct: Because for each position in the text, the algorithm may check many characters of the pattern, so pattern length matters too.
Understanding this simple search helps build a foundation for more efficient algorithms and shows you can analyze nested loops clearly.
"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 each position in the text one by one.Step 2: Compare with other methods
Other methods like hashing or preprocessing are not part of the naive approach.Final Answer:
Check every possible position in the text for the pattern -> Option AQuick Check:
Naive = Check all positions [OK]
- Thinking naive uses hashing
- Assuming pattern preprocessing is done
- Believing text is sorted first
Solution
Step 1: Determine loop range for matching
The outer loop must run from 0 to len(text)-len(pattern) to avoid out-of-range errors.Step 2: Check each option
for i := 0; i <= len(text)-len(pattern); i++ { correctly uses i <= len(text)-len(pattern). Others either go too far or use wrong limits.Final Answer:
for i := 0; i <= len(text)-len(pattern); i++ { -> Option AQuick Check:
Loop till text length minus pattern length [OK]
- Looping beyond valid start positions
- Starting loop from 1 instead of 0
- Using pattern length as loop limit
text := "banana"
pattern := "ana"
count := 0
for i := 0; i <= len(text)-len(pattern); i++ {
j := 0
for j < len(pattern) && text[i+j] == pattern[j] {
j++
}
if j == len(pattern) {
count++
}
}
fmt.Println(count)Solution
Step 1: Identify pattern matches in text
Check each position in "banana" for "ana": positions 1-3 and 3-5 match.Step 2: Count matches
Two matches found, so count is 2.Final Answer:
2 -> Option DQuick Check:
"ana" appears twice in "banana" [OK]
- Counting overlapping matches incorrectly
- Off-by-one errors in loop limits
- Assuming only first match counts
text := "abcabcabc"
pattern := "abc"
count := 0
for i := 0; i < len(text)-len(pattern); i++ {
j := 0
for j < len(pattern) && text[i+j] == pattern[j] {
j++
}
if j == len(pattern) {
count++
}
}
fmt.Println(count)Solution
Step 1: Analyze outer loop range
The loop runs from 0 to len(text)-len(pattern)-1, missing last valid start index.Step 2: Correct loop condition
Changing < to <= includes last position, fixing missed matches.Final Answer:
The outer loop should use <= instead of < -> Option BQuick Check:
Loop must cover last valid start index [OK]
- Using < instead of <= in outer loop
- Ignoring last possible match position
- Misunderstanding loop boundaries
text := "abracadabra"
pattern := "abra"
count := 0
for i := 0; i <= len(text)-len(pattern); i++ {
j := 0
for j < len(pattern) && text[i+j] == pattern[j] {
j++
}
if j == len(pattern) {
count++
}
}
fmt.Println(count)Solution
Step 1: Identify all pattern matches including overlaps
"abra" appears at positions 0-3 and 7-10 in "abracadabra".Step 2: Count total matches
Two matches found, so count is 2.Final Answer:
2 -> Option CQuick Check:
"abra" occurs twice overlapping allowed [OK]
- Counting only first match
- Missing second overlapping match
- Confusing substring positions
Ready to prove it?
Pass the test and this pattern moves unknown
