MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / levenshtein

Function levenshtein

nodedb-fts/src/fuzzy.rs:20–56  ·  view source on GitHub ↗

Fuzzy string matching via Levenshtein edit distance. Used for typo-tolerant full-text search. When an exact term match isn't found in the inverted index, fuzzy matching finds terms within a configurable edit distance. Distance thresholds are adaptive based on token length: - 1-3 chars: exact only (no fuzzy — too many false positives) - 4-6 chars: max distance 1 - 7+ chars: max distance 2 Compute

(a: &str, b: &str)

Source from the content-addressed store, hash-verified

18///
19/// Uses the two-row DP: O(min(a,b)) space, O(a*b) time.
20pub fn levenshtein(a: &str, b: &str) -> usize {
21 let a_chars: Vec<char> = a.chars().collect();
22 let b_chars: Vec<char> = b.chars().collect();
23 let a_len = a_chars.len();
24 let b_len = b_chars.len();
25
26 if a_len == 0 {
27 return b_len;
28 }
29 if b_len == 0 {
30 return a_len;
31 }
32
33 // Iterate the shorter string as the inner dimension.
34 let (short, long) = if a_len <= b_len {
35 (&a_chars[..], &b_chars[..])
36 } else {
37 (&b_chars[..], &a_chars[..])
38 };
39 let s_len = short.len();
40
41 let mut prev_row: Vec<usize> = (0..=s_len).collect();
42 let mut curr_row: Vec<usize> = vec![0; s_len + 1];
43
44 for (j, l_ch) in long.iter().enumerate() {
45 curr_row[0] = j + 1;
46 for (i, s_ch) in short.iter().enumerate() {
47 let cost = if s_ch == l_ch { 0 } else { 1 };
48 curr_row[i + 1] = (prev_row[i + 1] + 1)
49 .min(curr_row[i] + 1)
50 .min(prev_row[i] + cost);
51 }
52 std::mem::swap(&mut prev_row, &mut curr_row);
53 }
54
55 prev_row[s_len]
56}
57
58/// Maximum allowed edit distance for a given token length.
59///

Callers 1

fuzzy_matchFunction · 0.85

Calls 3

collectMethod · 0.80
lenMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected