1pub(crate) trait EditDistance {
3 fn edit_distance(&self, other: &Self) -> usize;
5}
6
7impl EditDistance for &[u8] {
8 fn edit_distance(&self, other: &Self) -> usize {
10 let mut dp = vec![vec![0; other.len() + 1]; self.len() + 1];
11
12 for i in 0..=self.len() {
13 for j in 0..=other.len() {
14 if i == 0 {
15 dp[i][j] = j;
16 } else if j == 0 {
17 dp[i][j] = i;
18 } else if self[i - 1] == other[j - 1] {
19 dp[i][j] = dp[i - 1][j - 1];
20 } else {
21 dp[i][j] = 1 + dp[i - 1][j - 1].min(dp[i - 1][j]).min(dp[i][j - 1]);
22 }
23 }
24 }
25
26 dp[self.len()][other.len()]
27 }
28}
29
30impl EditDistance for String {
31 fn edit_distance(&self, other: &Self) -> usize {
35 self.as_bytes().edit_distance(&other.as_bytes())
36 }
37}
38
39impl EditDistance for &str {
40 fn edit_distance(&self, other: &Self) -> usize {
44 self.as_bytes().edit_distance(&other.as_bytes())
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use rstest::rstest;
51
52 use super::*;
53
54 #[rstest]
55 #[case("kitten", "sitting", 3)]
56 #[case("flaw", "lawn", 2)]
57 #[case("intention", "execution", 5)]
58 #[case("", "", 0)]
59 #[case("a", "", 1)]
60 #[case("", "a", 1)]
61 fn test_edit_distance(#[case] s1: &str, #[case] s2: &str, #[case] expected: usize) {
62 let distance = s1.edit_distance(&s2);
63 assert_eq!(distance, expected);
64 }
65}