KMP算法

100 阅读1分钟

KMP算法 rust代码实现 实现步骤:

  1. 求解 next 数组,用于模式串 p和目标串 s不匹配时,知道回退位置
  2. 对模式串 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
}