KMP Pattern Matching Algorithm in DSA C# - Time & Space Complexity
We want to understand how the KMP algorithm's running time changes as the text and pattern sizes grow.
Specifically, how fast can it find a pattern inside a text?
Analyze the time complexity of the following KMP pattern matching code.
// Compute longest prefix suffix (LPS) array
void ComputeLPSArray(string pattern, int[] lps) {
int length = 0; // length of previous longest prefix suffix
int i = 1;
while (i < pattern.Length) {
if (pattern[i] == pattern[length]) {
length++;
lps[i] = length;
i++;
} else {
if (length != 0) length = lps[length - 1];
else {
lps[i] = 0;
i++;
}
}
}
}
// KMP search
void KMPSearch(string pattern, string text) {
int[] lps = new int[pattern.Length];
ComputeLPSArray(pattern, lps);
int i = 0, j = 0;
while (i < text.Length) {
if (pattern[j] == text[i]) {
i++; j++;
}
if (j == pattern.Length) {
// pattern found at i-j
j = lps[j - 1];
} else if (i < text.Length && pattern[j] != text[i]) {
if (j != 0) j = lps[j - 1];
else i++;
}
}
}
This code finds all occurrences of a pattern inside a text efficiently using the KMP algorithm.
Look at the loops and repeated steps:
- Primary operation: Comparing characters of pattern and text.
- How many times: Each character in text and pattern is visited at most twice during the search and LPS computation.
As the text length (n) and pattern length (m) grow, the operations grow roughly in a straight line.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 (text), 3 (pattern) | About 20 operations |
| 100 (text), 10 (pattern) | About 220 operations |
| 1000 (text), 50 (pattern) | About 1050 operations |
Pattern observation: The operations increase roughly proportional to the sum of text and pattern lengths.
Time Complexity: O(n + m)
This means the algorithm checks characters in the text and pattern only once or twice, making it very efficient.
[X] Wrong: "KMP is slower than simple search because it does extra work building the LPS array."
[OK] Correct: The LPS array is built in linear time and helps avoid re-checking characters, so overall KMP is faster on large inputs.
Understanding KMP's time complexity shows you can analyze efficient algorithms that avoid repeated work, a key skill in coding interviews.
"What if we changed the pattern to be very long compared to the text? How would the time complexity change?"
Practice
Solution
Step 1: Understand the goal of KMP
KMP is designed to search for a pattern inside a larger text efficiently without rechecking characters unnecessarily.Step 2: Compare with other options
Sorting, reversing strings, and calculating factorials are unrelated to pattern searching.Final Answer:
To find occurrences of a pattern string within a text efficiently -> Option AQuick Check:
KMP = Pattern searching [OK]
- Confusing KMP with sorting algorithms
- Thinking KMP reverses strings
- Assuming KMP calculates factorials
Solution
Step 1: Understand array declaration in C#
In C#, arrays are declared with type[], then new type[size]. So int[] lps = new int[pattern.Length]; is correct.Step 2: Check other options
int lps = new int[pattern.Length]; misses [] for array type, C uses invalid syntax, D uses C/C++ style which is invalid in C#.Final Answer:
int[] lps = new int[pattern.Length]; -> Option DQuick Check:
C# array syntax = int[] name = new int[size]; [OK]
- Missing [] in array type declaration
- Using C/C++ style array declaration in C#
- Trying to instantiate array without size
string text = "ABABABC";
string pattern = "ABABC";
List<int> matches = KMPSearch(pattern, text);
Console.WriteLine(string.Join(",", matches));
// Assume KMPSearch returns list of start indices where pattern matches textSolution
Step 1: Analyze the text and pattern
Text: A B A B A B C Pattern: A B A B C Check where pattern fully matches text starting index.Step 2: Find matching index
At index 0: text substring "ABABA" does not match "ABABC" (last char mismatch) At index 1: substring "BABAB" no match At index 2: substring "ABABC" matches pattern exactly.Final Answer:
2 -> Option CQuick Check:
Pattern found at index 2 only [OK]
- Assuming multiple matches without checking full pattern
- Off-by-one errors in indexing
- Confusing partial matches as full matches
int[] ComputeLPS(string pattern) {
int[] lps = new int[pattern.Length];
int length = 0;
int i = 1;
while (i < pattern.Length) {
if (pattern[i] == pattern[length]) {
length++;
lps[i] = length;
i++;
} else {
if (length != 0) {
length = lps[length];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}Solution
Step 1: Understand lps update logic
When mismatch occurs and length != 0, length should be updated to lps[length - 1], not lps[length].Step 2: Check other parts
Array size is correct, while loop is valid, return statement exists. So only length update is wrong.Final Answer:
Incorrect update of length in else block: should be length = lps[length - 1]; -> Option AQuick Check:
lps update uses length-1 index [OK]
- Using lps[length] instead of lps[length - 1]
- Confusing loop types causing infinite loops
- Forgetting to return lps array
Solution
Step 1: Identify all occurrences of pattern in text
Text: A A A A A B A A A B A Pattern: A A A B A Check each possible start index:Step 2: Check matches at each index
Index 0: substring "AAAAA" no (pattern ends with B) Index 1: substring "AAAAB" no (pattern ends with A) Index 2: substring "AAABA" yes (match 1) Index 3: substring "AABAA" no Index 4: substring "ABAAA" no Index 5: substring "BAAAB" no Index 6: substring "AAABA" yes (match 2) Index 7: substring "AABA" incomplete Index 8: substring "ABA" incomplete Check carefully for overlapping matches.Step 3: Re-check for missed matches
Check index 1 carefully: substring "AAAAB" pattern is "AAABA" so no match. Check index 0 carefully: substring "AAAAA" pattern ends with B, no match. Check index 6: "AAABA" matches pattern exactly (match 2). Check index 2: "AAABA" matches pattern exactly (match 1). No other matches found.Step 4: Check index 3 for overlapping match
At index 3: substring "AABAA" does not match pattern "AAABA". At index 4: substring "ABAAA" no match. At index 5: substring "BAAAB" no match. At index 7: substring "AABA" incomplete. So total matches found: 2.Final Answer:
2 -> Option BQuick Check:
Pattern found twice in text [OK]
- Counting partial matches as full matches
- Missing overlapping matches
- Off-by-one errors in substring indexing
Ready to prove it?
Pass the test and this pattern moves unknown
