Rust-如何在vec中搜索子集-并找到subvec的起始索引?

时间:2019-07-19 19:20:12

标签: algorithm rust

如果我有一个vec,如何搜索它是否包含另一个vec-并返回该subvec开始的索引?

let mut haystack = vec!(0, 0, 0, 1, 48, 120, 49, 49, 1, 0);
let mut needle = vec!(48, 120, 49, 49);

它返回4(原始子集中的起始索引)(或者,在这种情况下,它将返回一个包含4的结果-如果根本找不到它将会出错)。

1 个答案:

答案 0 :(得分:0)

这是经典的string search problem。 @Willem Van Onsem建议使用KMP算法,但是您应该从朴素的算法开始。

对于haystack的每个索引,尝试比较与needle相同长度的字符串,并从haystack中的该索引开始,将其与needle本身。

看看这个:

0   0   0   1   48  120 49  49  1   0
48  120 49  49
x fail
    48  120 49  49
    x fail
        48  120 49  49
        x fail
            48  120 49  49
            x fail
                48  120 49  49
                -   -   -   - match!

x表示元素不同,-相同。在每个x上,移至haystack的下一个元素(这与KMP的不同之处在于,KMP可能一次移动多个元素)。

在Rust中,您将编写如下内容:

fn find1(haystack: &Vec<i32>, needle: &Vec<i32>) -> i64 {
    for i in 0..haystack.len()-needle.len()+1 { // last indices of haystack are too far right to get a match
        let mut j = 0;
        while j < needle.len() { // check every char of needle
            if needle[j] != haystack[i+j] { // doesn't match
                break; // try the next i
            }
            j += 1; // else: match so far
        }
        if j == needle.len() { // no break: a full match was found
            return i as i64;
        }
    }
    return -1; // not a single full match
}

当然,您可以使用一些Rust功能来缩短代码(并避免上面的C型样式):

fn find2(haystack: &Vec<i32>, needle: &Vec<i32>) -> Option<usize> {
    for i in 0..haystack.len()-needle.len()+1 {
        if haystack[i..i+needle.len()] == needle[..] {
            return Some(i);
        }
    }
    return None;
}

或者您愿意的话,还可以使用功能样式:

fn find3(haystack: &Vec<i32>, needle: &Vec<i32>) -> Option<usize> {
    (0..haystack.len()-needle.len()+1)
        .filter(|&i| haystack[i..i+needle.len()] == needle[..]).next()
}

如果您了解朴素的算法及其朴素的实现,则可以使用更快的算法。