What if you could find a phrase in a huge book without ever looking back twice?
Why KMP Pattern Matching Algorithm in DSA Rust?
Imagine you have a huge book and you want to find every place where a certain phrase appears. You try to look for the phrase by checking each word one by one from the start every time you find a mismatch.
This manual way is very slow and tiring because you keep going back and checking the same words again and again. It wastes a lot of time and can easily cause mistakes if you lose track.
The KMP Pattern Matching Algorithm helps by remembering where to continue checking after a mismatch, so you never check the same part twice. It makes searching fast and smooth, even in very long texts.
fn search(text: &str, pattern: &str) {
let n = text.len();
let m = pattern.len();
let end = n.saturating_sub(m).saturating_add(1);
for i in 0..end {
if &text[i..i + m] == pattern {
println!("Found at {}", i);
}
}
}fn compute_lps(pattern: &str) -> Vec<usize> {
let pi = pattern.as_bytes();
let m = pi.len();
let mut lps = vec![0; m];
let mut j = 0;
for i in 1..m {
while j > 0 && pi[i] != pi[j] {
j = lps[j - 1];
}
if pi[i] == pi[j] {
j += 1;
}
lps[i] = j;
}
lps
}
fn kmp_search(text: &str, pattern: &str) {
if pattern.is_empty() {
return;
}
let lps = compute_lps(pattern);
let mut i = 0;
let mut j = 0;
let text_bytes = text.as_bytes();
let pattern_bytes = pattern.as_bytes();
while i < text_bytes.len() {
if text_bytes[i] == pattern_bytes[j] {
i += 1;
j += 1;
if j == pattern_bytes.len() {
println!("Found at {}", i - j);
j = lps[j - 1];
}
} else if j > 0 {
j = lps[j - 1];
} else {
i += 1;
}
}
}It enables lightning-fast searching of patterns inside huge texts without repeating work.
Search engines use this to quickly find your search words inside billions of web pages.
Manual searching repeats checks and wastes time.
KMP remembers where to continue after mismatches.
KMP makes pattern searching efficient and reliable.
Practice
KMP Pattern Matching Algorithm?Solution
Step 1: Understand the problem KMP solves
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 AQuick Check:
KMP = Pattern search [OK]
- Confusing KMP with sorting algorithms
- Thinking KMP reverses strings
- Assuming KMP calculates mathematical functions
Solution
Step 1: Understand prefix table initialization
The prefix table (lps) needs to be mutable and initialized with zeros for the length of the pattern.Step 2: Check each option
let mut lps: Vec<usize> = vec![0; pattern.len()]; correctly creates a mutable vector of usize with zeros. let lps = [0; pattern.len()]; creates an array but Rust arrays need constant size. let mut lps = Vec::new(); creates an empty vector without size. let lps: Vec<i32> = Vec::with_capacity(pattern.len()); creates a vector with capacity but no elements initialized.Final Answer:
let mut lps: Vec<usize> = vec![0; pattern.len()]; -> Option DQuick Check:
Mutable zero-filled vector = let mut lps: Vec<usize> = vec![0; pattern.len()]; [OK]
- Using fixed-size arrays without constant size
- Not initializing vector elements
- Using wrong data types for lps
fn main() {
let text = "ABABABCABABC";
let pattern = "ABABC";
let positions = kmp_search(text, pattern);
println!("{:?}", positions);
}
fn kmp_search(text: &str, pattern: &str) -> Vec<usize> {
let lps = compute_lps(pattern);
let mut result = Vec::new();
let mut i = 0;
let mut j = 0;
while i < text.len() {
if text.as_bytes()[i] == pattern.as_bytes()[j] {
i += 1;
j += 1;
if j == pattern.len() {
result.push(i - j);
j = lps[j - 1];
}
} else if j > 0 {
j = lps[j - 1];
} else {
i += 1;
}
}
result
}
fn compute_lps(pattern: &str) -> Vec<usize> {
let mut lps = vec![0; pattern.len()];
let mut length = 0;
let mut i = 1;
while i < pattern.len() {
if pattern.as_bytes()[i] == pattern.as_bytes()[length] {
length += 1;
lps[i] = length;
i += 1;
} else if length > 0 {
length = lps[length - 1];
} else {
lps[i] = 0;
i += 1;
}
}
lps
}Solution
Step 1: Understand KMP search output
The function returns starting indices where the pattern "ABABC" appears in the text "ABABABCABABC".Step 2: Trace pattern matches
Pattern matches at index 2 ("ABABC" in "ABABABC") and index 7 ("ABABC" in "ABABC"), so output is [2, 7].Final Answer:
[2, 7] -> Option BQuick Check:
Pattern found at indices 2 and 7 [OK]
- Counting overlapping matches incorrectly
- Confusing indices starting at 0 or 1
- Misreading pattern occurrences
fn compute_lps(pattern: &str) -> Vec<usize> {
let mut lps = vec![0; pattern.len()];
let mut length = 0;
let mut i = 0;
while i < pattern.len() {
if pattern.as_bytes()[i] == pattern.as_bytes()[length] {
length += 1;
lps[i] = length;
i += 1;
} else if length > 0 {
length = lps[length - 1];
} else {
lps[i] = 0;
i += 1;
}
}
lps
}Solution
Step 1: Analyze loop initialization
The prefix table computation starts comparing from the second character, so i must start at 1, not 0.Step 2: Check other variables and return type
Length starts at 0 correctly, lps vector type usize is correct, and returning a vector is expected.Final Answer:
The loop should start with i = 1, not 0 -> Option AQuick Check:
Start i at 1 for prefix table [OK]
- Starting loop at 0 causing incorrect prefix values
- Changing length initialization wrongly
- Wrong return type assumptions
Solution
Step 1: Understand KMP time complexity
KMP processes the text and pattern in linear time by using the prefix table to skip unnecessary comparisons.Step 2: Compare with other complexities
Naive search is O(n*m), binary search is unrelated, and prefix table computation is O(m), not quadratic.Final Answer:
O(n + m) because KMP avoids rechecking characters using the prefix table -> Option CQuick Check:
KMP = linear time O(n + m) [OK]
- Assuming nested loops cause O(n*m)
- Confusing prefix table with binary search
- Thinking prefix table is quadratic
Ready to prove it?
Pass the test and this pattern moves unknown
