KMP算法 rust代码实现 实现步骤:
- 求解 next 数组,用于模式串 p和目标串 s不匹配时,知道回退位置
- 对模式串 p和目标串 s进行匹配
fn main() {
let v = kmp("ABCDEFAB", "AB");
println!("{:?}", v);
}
// lps(longest prefix suffix),求解next数组
fn lps(s: &str) -> Vec<usize> {
if s.is_empty() {
return vec![];
}
let mut j: usize = 0;
let mut res = vec![0; s.len()];
for i in 1..s.len() {
while &s[i..i+1] != &s[j..j+1] && j > 1 {
j = res[j - 1];
}
if &s[i..i+1] == &s[j..j+1] {
j += 1;
res[i] = j;
}
}
res
}
// 返回匹配的开始索引
fn kmp(s: &str, p: &str) -> Vec<usize> {
let mut result: Vec<usize> = vec![];
let next = lps(p);
let mut j: usize = 0;
for (i,_) in s.char_indices() {
let val = &s[i..i+1];
// 根据next数组,回退 j指针
if val != &p[j..j+1] && j > 0 {
j = next[j - 1];
}
if val == &p[j..j+1] {
j += 1;
// 找到匹配的,重置 j = 0
if j == p.len() {
result.push(i + 1 - j);
j = 0;
}
}
}
result
}