use crate::*;
pub fn slice_find<T: Ord>(haystack: &[T], needle: &[T]) -> Option<usize> {
let haystack_len = haystack.len();
let needle_len = needle.len();
if needle_len == 0 {
return Some(0); }
if needle_len > haystack_len {
return None; }
if needle_len == 1 {
return haystack.iter().position(|c| { c == &needle[0] });
}
if needle_len == haystack_len {
if haystack == needle {
return Some(0);
} else {
return None;
}
}
let mut bm_bc = BTreeMap::new();
for (i, item) in needle.iter().enumerate().take(needle_len - 1) {
bm_bc.insert(item, needle_len - i - 1);
}
let first_item = &needle[0];
let middle_item = &needle[needle_len / 2];
let last_item = &needle[needle_len - 1];
let mut pos = 0;
while pos <= (haystack_len - needle_len) {
let item = &haystack[pos+needle_len-1];
if item == last_item
&& &haystack[pos] == first_item
&& &haystack[pos + needle_len/2] == middle_item
&& &haystack[pos+1 .. pos+needle_len-1] == &needle[1 .. needle_len-1]
{
return Some(pos);
}
pos += bm_bc.get(item).copied().unwrap_or(1);
}
None
}
pub fn slice_contains<T: Ord>(haystack: &[T], needle: &[T]) -> bool {
slice_find(haystack, needle).is_some()
}