use std::cmp::min;
use Metric;
#[derive(Debug)]
pub struct Levenshtein;
impl<K: AsRef<str> + ?Sized> Metric<K> for Levenshtein
{
fn distance(&self, a: &K, b: &K) -> u64 {
let str_a: &str = a.as_ref();
let str_b: &str = b.as_ref();
let len_a = str_a.chars().count();
let len_b = str_b.chars().count();
if len_a == 0 {
return len_b as u64;
}
if len_b == 0 {
return len_a as u64;
}
let a_lower = str_a.to_lowercase();
let b_lower = str_b.to_lowercase();
let mut d: Vec<Vec<usize>> = Vec::new();
for j in 0..(len_b + 1) {
let mut cur_vec = Vec::new();
for i in 0..(len_a + 1) {
if j == 0 {
cur_vec.push(i);
} else if i == 0 {
cur_vec.push(j);
} else {
cur_vec.push(0);
}
}
d.push(cur_vec);
}
for (j, chr_b) in b_lower.chars().enumerate() {
for (i, chr_a) in a_lower.chars().enumerate() {
if chr_a == chr_b {
d[j + 1][i + 1] = d[j][i];
} else {
let deletion = d[j + 1][i] + 1;
let insertion = d[j][i + 1] + 1;
let substitution = d[j][i] + 1;
d[j + 1][i + 1] = min(min(deletion, insertion), substitution);
}
}
}
d[len_b][len_a] as u64
}
}