likes
comments
collection
share

Rust:字符串匹配Rabin-Karp 算法

作者站长头像
站长
· 阅读数 19

Rabin-Karp 算法

也可以叫 Karp-Rabin 算法,由 Richard M. Karp 和 Michael O. Rabin 在 1987 年发表,它也是用来解决多模式串匹配问题的。它的实现方式有点与众不同,首先是计算两个字符串的哈希值,然后通过比较这两个哈希值的大小来判断是否出现匹配。

2. 原理

Rabin-Karp 算法使用哈希函数来计算字符串的哈希值。哈希函数是一种将任意长度的输入数据映射为固定长度输出的函数。在 Rabin-Karp 算法中,我们使用哈希函数来计算字符串的哈希值,并比较能否在文本字符串中得到相同的哈希值。

例如,假设我们有一个文本字符串 “hello world” 和一个模式字符串 “world”。我们可以使用哈希函数来计算这两个字符串的哈希值。如果这两个哈希值相等,那么我们就可以认为模式字符串在文本字符串中出现了。

3. 实现

下面是一个使用 Rust 语言实现的 Rabin-Karp 算法示例:

fn rabin_karp(text: &str, pattern: &str) -> Vec<usize> {
    let n = text.len();
    let m = pattern.len();
    let base: u64 = 256;
    let modulus: u64 = 101;
    let mut res = Vec::new();

    if m > n {
        return res;
    }

    // Precompute (base ** (m - 1)) % modulus
    let mut h: u64 = 1;
    for _ in 0..m - 1 {
        h = (h * base) % modulus;
    }

    // Compute the hash value of pattern and first window of text
    let mut p: u64 = 0;
    let mut t: u64 = 0;
    for i in 0..m {
        p = (base * p + pattern.as_bytes()[i] as u64) % modulus;
        t = (base * t + text.as_bytes()[i] as u64) % modulus;
    }

    // Slide the pattern over text one by one
    for i in 0..n - m + 1 {
        // Check the hash values of current window of text and pattern
        if p == t {
            // Check if the characters are actually the same
            if text[i..i + m] == *pattern {
                res.push(i);
            }
        }

        // Calculate the hash value for next window of text
        if i < n - m {
            t = (base * (t - text.as_bytes()[i] as u64 * h) + text.as_bytes()[i + m] as u64) % modulus;

            // We might get negative value of t, converting it to positive
            if t < 0 {
                t += modulus;
            }
        }
    }

    res
}

上面的代码实现了 Rabin-Karp 算法。它首先计算模式字符串和文本字符串第一个窗口的哈希值,然后逐个滑动窗口并比较哈希值。如果哈希值相等,则进一步比较字符是否相同。如果字符相同,则将当前位置添加到结果中。

复杂度分析:Rabin-Karp 算法的时间复杂度为 O(n),其中 n 是文本字符串的长度。空间复杂度为 O(1)。

4. 应用

Rabin-Karp 算法主要用来检测文章抄袭,比如 Semantic Scholar 的检测系统。它能够快速地在论文中搜寻原材料中的句子,同时忽略诸如大小写与标点等细节。

Rabin-Karp 算法具有一些优点,例如它能够快速地检测文章抄袭,并且能够处理大量数据。但是它也有一些缺点,例如它对于哈希碰撞非常敏感,并且在最坏情况下时间复杂度会退化为 O(nm),其中 n 是文本字符串的长度,m 是模式字符串的长度。

Rabin-Karp 算法是一种非常实用的字符串匹配算法,它能够快速地解决多模式串匹配问题,并且具有良好的性能。from刘金,转载请注明原文链接。感谢!