#[derive(Clone)]
pub struct String<'a>{
pub ch: &'a [char],
pub len: usize,
}
impl<'a> String<'a> {
pub fn new(ch: &'a [char]) -> String<'a> {
String {
ch,
len: ch.len()
}
}
#[allow(non_snake_case)]
pub fn index_BF(&self, other: &String, pos: usize) -> usize {
let mut i = pos;
let mut j = 0;
while i < self.len && j < other.len {
if self.ch[i] == other.ch[j] {
i += 1;
j += 1;
} else {
i = i - j + 1;
j = 0;
}
}
if j == other.len {
i - j
} else {
0
}
}
}
fn next<T>(pattern: &[T]) -> Vec<usize>
where
T: PartialEq + Eq,
{
let mut next = vec![0; pattern.len()];
if pattern.is_empty() {
return next;
}
next[0] = 0;
let mut i = 1;
let mut j = 0;
while i < pattern.len() {
if pattern[i] == pattern[j] {
j += 1;
next[i] = j;
i += 1;
} else if j == 0 {
next[i] = 0;
i += 1;
} else {
j = next[j - 1];
}
}
next
}
#[allow(non_snake_case)]
pub fn index_KMP<T>(main:&[T],pattern:&[T])->Option<usize>
where T:PartialEq+Eq,
{
if pattern.is_empty(){
return Some(0);
}
let next=next(pattern);
let mut i=0usize;
let mut j=0usize;
while i<main.len() && j<pattern.len() {
if j==0 || main[i]==pattern[j] {
i+=1;
j+=1;
}else {
j=next[j-1];
}
}
if j==pattern.len() {
Some(i-j)
}else {
None
}
}
#[cfg(test)]
mod test{
use crate::linear::string;
#[test]
fn test_index_bf() {
let s1 = string::String::new(&['a','b','a','b','c','a','b','c','a','c','b','a','b']);
let s2 = string::String::new(&['a','b','c','a','c']);
assert_eq!(s1.index_BF(&s2, 0), 5);
let s3 = string::String::new(&['x','y','z']);
assert_eq!(s1.index_BF(&s3, 0), 0);
let s2_clone = s2.clone();
assert_eq!(s1.index_BF(&s2_clone, 6), 0);
}
#[test]
fn test_index_kmp() {
assert_eq!(
string::index_KMP(&['a','b','a','b','c','a','b','c','a','c','b','a','b'], &['a','b','c','a','c']),
Some(5)
);
assert_eq!(
string::index_KMP(&['a','b','c'], &['x','y','z']),
None
);
assert_eq!(
string::index_KMP(&['a','b','c'], &[]),
Some(0)
);
}
}