📖 Scenario: Imagine you are building a text search tool that quickly finds a smaller word or phrase inside a large document. This tool uses a smart method called the KMP algorithm to avoid checking the same letters again and again.
🎯 Goal: You will build the KMP pattern matching algorithm in Rust step-by-step. This algorithm helps find all places where a pattern appears inside a text efficiently.
📋 What You'll Learn
Create a function to build the longest prefix suffix (LPS) array for the pattern
Create a function to use the LPS array to find all pattern matches in the text
Print the starting indexes of all matches found
💡 Why This Matters
🌍 Real World
Text editors, search engines, and DNA sequence analysis use pattern matching algorithms like KMP to quickly find patterns in large data.
💼 Career
Understanding KMP helps in roles involving text processing, software development, and algorithm optimization.
Progress0 / 4 steps
1
Create the pattern and text variables
Create a variable called pattern with the value "ABABCABAB" and a variable called text with the value "ABABDABACDABABCABAB".
DSA Rust
Hint
Use let to create variables for pattern and text with the exact strings given.
2
Build the longest prefix suffix (LPS) array
Create a function called build_lps that takes a &str called pattern and returns a Vec. Inside it, create a mutable vector lps of length pattern.len() filled with zeros. Use variables length set to 0 and i set to 1. Use a while loop with condition i < pattern.len() to fill the lps array following the KMP logic. Return lps at the end.
DSA Rust
Hint
Remember to compare characters using bytes and update length and lps according to the KMP prefix logic.
3
Implement the KMP search function
Create a function called kmp_search that takes text: &str and pattern: &str and returns a Vec of starting indexes where the pattern is found. Inside, call build_lps(pattern) to get the lps array. Use variables i and j set to 0 to track positions in text and pattern. Use a while loop with condition i < text.len() to compare characters and find matches using the KMP logic. Collect all match start indexes in a vector called result and return it.
DSA Rust
Hint
Use two indexes i and j to scan text and pattern. Use the lps array to skip characters when mismatch happens.
4
Print all pattern match positions
Call the kmp_search function with text and pattern variables. Store the result in a variable called matches. Print the matches vector.
DSA Rust
Hint
The pattern appears starting at index 10 in the text. Print the vector of matches using println!("{:?}", matches);.
Practice
(1/5)
1. What is the main purpose of the KMP Pattern Matching Algorithm?
easy
A. To find occurrences of a pattern string within a text efficiently
B. To sort an array of numbers quickly
C. To reverse a string in linear time
D. To calculate the factorial of a number
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 A
Quick Check:
KMP = Pattern search [OK]
Hint: KMP is about searching patterns fast in text [OK]
Common Mistakes:
Confusing KMP with sorting algorithms
Thinking KMP reverses strings
Assuming KMP calculates mathematical functions
2. Which of the following is the correct way to declare the prefix table (lps array) in Rust for KMP algorithm?
easy
A. let mut lps = Vec::new();
B. let lps = [0; pattern.len()];
C. let lps: Vec<i32> = Vec::with_capacity(pattern.len());
D. let mut lps: Vec<usize> = vec![0; pattern.len()];
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 D