String Pattern Matching Naive in DSA Java - 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 naiveSearch(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.charAt(i + j) != pattern.charAt(j)) {
break;
}
}
if (j == m) {
return i; // pattern found at index i
}
}
return -1; // pattern not found
}
This code checks every possible place 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 a substring of the text.
- How many times: For each position in the text (about n - m + 1 times), we compare 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 size of the text times the size 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, we may need to check all characters of the pattern, so pattern length matters too.
Understanding this simple search helps build a foundation for more efficient methods and shows you can analyze nested loops clearly.
"What if we stopped searching after the first mismatch without checking all pattern characters? How would the time complexity change in the best and worst cases?"
Practice
Solution
Step 1: Understand the naive approach
The naive algorithm tries to match the pattern starting at every position in the text.Step 2: Compare pattern characters at each position
At each position, it compares characters one by one until a mismatch or full match is found.Final Answer:
Check every possible position in the text to see if the pattern matches -> Option DQuick Check:
Naive = Check all positions [OK]
- Thinking naive uses hashing
- Assuming it preprocesses pattern
- Confusing with advanced algorithms like KMP
text length is n and pattern length is m?Solution
Step 1: Determine valid start positions
Pattern of length m can only start at positions 0 to n-m in text of length n.Step 2: Write loop condition
Loop must run from i = 0 to i <= n - m to avoid index out of bounds.Final Answer:
for (int i = 0; i <= n - m; i++) -> Option BQuick Check:
Loop till n-m inclusive [OK]
- Looping till n causes index errors
- Looping till m is too short
- Using < instead of <= for 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.charAt(i + j) != pattern.charAt(j)) {
break;
}
}
if (j == pattern.length()) {
count++;
}
}
System.out.println(count);Solution
Step 1: Identify pattern occurrences
Pattern "abc" appears at positions 0, 3, and 6 in text "abcabcabc".Step 2: Count matches in nested loops
Each full match increments count. Total matches found = 3.Final Answer:
3 -> Option AQuick Check:
Pattern "abc" occurs 3 times [OK]
- Counting overlapping matches incorrectly
- Breaking loop too early
- Off-by-one errors in loop conditions
String text = "hellohello";
String pattern = "hello";
for (int i = 0; i < text.length() - pattern.length(); i++) {
int j;
for (j = 0; j < pattern.length(); j++) {
if (text.charAt(i + j) != pattern.charAt(j)) {
break;
}
}
if (j == pattern.length()) {
System.out.println("Pattern found at index " + i);
}
}Solution
Step 1: Check outer loop range
Loop runs from i = 0 to i < text.length() - pattern.length(), missing last valid start index.Step 2: Correct loop condition
It should be i <= text.length() - pattern.length() to include last possible match.Final Answer:
Loop condition should be i <= text.length() - pattern.length() -> Option AQuick Check:
Include last index with <= [OK]
- Using < instead of <= in outer loop
- Starting inner loop from wrong index
- Confusing pattern and text lengths
Which change is correct?
Solution
Step 1: Understand overlapping matches
Overlapping means pattern can start inside a previous match, so we must check every next position.Step 2: Adjust index increment
Instead of jumping by pattern length after a match, increment index by 1 to check next position.Final Answer:
After finding a match at index i, increment i by 1 instead of pattern length -> Option CQuick Check:
Increment by 1 to count overlaps [OK]
- Skipping overlapping positions by jumping pattern length
- Using hashing which is unrelated here
- Ignoring overlaps completely
Ready to prove it?
Pass the test and this pattern moves unknown
