KMP Pattern Matching Algorithm in DSA Python - 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.
def compute_lps(pattern):
lps = [0] * len(pattern)
length = 0
i = 1
while i < len(pattern):
if pattern[i] == pattern[length]:
length += 1
lps[i] = length
i += 1
else:
if length != 0:
length = lps[length - 1]
else:
lps[i] = 0
i += 1
return lps
This code builds the longest prefix suffix (LPS) array for the pattern, which helps skip unnecessary comparisons.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that processes each character of the pattern once.
- How many times: At most twice per character, but overall linear to pattern length.
The number of operations grows roughly in a straight line with the pattern length.
| Input Size (pattern length) | Approx. Operations |
|---|---|
| 10 | About 20 |
| 100 | About 200 |
| 1000 | About 2000 |
Pattern observation: Doubling the pattern size roughly doubles the work done.
Time Complexity: O(n + m)
This means the algorithm checks each character of the text and pattern at most once, making it very efficient.
[X] Wrong: "The KMP algorithm has a nested loop causing O(n*m) time like naive search."
[OK] Correct: KMP cleverly uses the LPS array to avoid rechecking characters, so it never goes back in the text, keeping time linear.
Understanding KMP's time complexity shows you can analyze efficient algorithms that improve over simple methods, a key skill in interviews.
"What if the pattern is much longer than the text? How would that affect the time complexity?"
Practice
Solution
Step 1: Understand the goal of KMP algorithm
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 factorial calculations are unrelated to pattern searching.Final Answer:
To find occurrences of a pattern string within a text efficiently -> Option DQuick Check:
KMP = Pattern search [OK]
- Confusing KMP with sorting algorithms
- Thinking KMP reverses strings
- Assuming KMP calculates mathematical functions
Solution
Step 1: Understand the prefix table initialization
The prefix table (lps array) stores lengths of longest proper prefix which is also suffix for each prefix of the pattern. It must be initialized with zeros for all positions.Step 2: Check each option
lps = [0] * len(pattern) correctly initializes lps with zeros for the entire pattern length. lps = [] is empty list, which is incomplete. lps = [1] * len(pattern) initializes with ones, which is incorrect. lps = None sets None, which is invalid.Final Answer:
lps = [0] * len(pattern) -> Option AQuick Check:
Prefix table starts with zeros [OK]
- Initializing lps with ones instead of zeros
- Leaving lps empty
- Assigning None to lps
def compute_lps(pattern):
lps = [0] * len(pattern)
length = 0
i = 1
while i < len(pattern):
if pattern[i] == pattern[length]:
length += 1
lps[i] = length
i += 1
else:
if length != 0:
length = lps[length - 1]
else:
lps[i] = 0
i += 1
return lps
pattern = "ABABC"
lps = compute_lps(pattern)
print(lps)Solution
Step 1: Compute lps array for pattern "ABABC"
Index 0: lps[0] = 0 (always zero)
Index 1: pattern[1] = 'B' != pattern[0] = 'A', lps[1] = 0
Index 2: pattern[2] = 'A' == pattern[0] = 'A', lps[2] = 1
Index 3: pattern[3] = 'B' == pattern[1] = 'B', lps[3] = 2
Index 4: pattern[4] = 'C' != pattern[2] = 'A', lps[4] = 0Step 2: Final lps array
The computed lps array is [0, 0, 1, 2, 0].Final Answer:
[0, 0, 1, 2, 0] -> Option BQuick Check:
lps for "ABABC" = [0,0,1,2,0] [OK]
- Confusing lps values with pattern indices
- Assuming all zeros or all increasing values
- Mixing up characters when comparing
def compute_lps(pattern):
lps = [0] * len(pattern)
length = 0
i = 0
while i < len(pattern):
if pattern[i] == pattern[length]:
length += 1
lps[i] = length
i += 1
else:
if length != 0:
length = lps[length - 1]
else:
lps[i] = 0
i += 1
return lpsSolution
Step 1: Analyze the loop initialization
In KMP prefix table computation, the first character's lps is always zero and we start comparing from the second character, so i should start at 1.Step 2: Check the given code
The code starts with i = 0, which causes comparing pattern[0] with pattern[0] immediately, leading to incorrect lps values and infinite loop risk.Final Answer:
The loop should start with i = 1, not i = 0 -> Option AQuick Check:
Start i at 1 for prefix table [OK]
- Starting loop at zero causing wrong comparisons
- Initializing lps with ones instead of zeros
- Returning wrong variable
"ABABDABACDABABCABAB" and pattern "ABABCABAB", how many times does the pattern appear in the text using KMP algorithm?Solution
Step 1: Understand the pattern and text
The pattern "ABABCABAB" is searched inside the text "ABABDABACDABABCABAB" using KMP which efficiently finds all occurrences.Step 2: Identify pattern occurrences
By scanning the text:
- Occurrence starts at index 10 (substring "ABABCABAB")
So pattern appears 1 time.Final Answer:
1 -> Option CQuick Check:
Pattern appears once in text [OK]
- Counting only first occurrence
- Ignoring overlapping matches
- Misreading pattern or text
Ready to prove it?
Pass the test and this pattern moves unknown
