如果我有一个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的结果-如果根本找不到它将会出错)。
答案 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()
}
如果您了解朴素的算法及其朴素的实现,则可以使用更快的算法。