Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Weakest-Link Floor

The default scoring is additive: each edit contributes independently, so a single very-dissimilar substitution can be diluted by an otherwise-excellent long match. One sim = 0 substitution in a 20-grapheme pattern still scores ~0.93 and would pass a 0.8 threshold.

Sometimes that’s wrong: you want to say no individual substitution may be too weak, no matter how good the rest of the match is. That is the “weakest link” bound from the underlying research, exposed as min_symbol_similarity.

Setting a floor

use fuzzy_aho_corasick::{FuzzyAhoCorasickBuilder, FuzzyLimits, SearchOptions};

let engine = FuzzyAhoCorasickBuilder::new()
    .fuzzy(FuzzyLimits::new().edits(1))
    .case_insensitive(true)
    .min_symbol_similarity(0.3) // reject any substitution below 0.3 similarity
    .build(["vestibulum"]);

// e↔x has similarity 0 -> the substitution is rejected outright.
assert!(engine.search("vxstibulum", &SearchOptions::new().threshold(0.8)).unwrap().is_empty());

// u↔o has similarity 0.6 -> allowed.
assert_eq!(engine.search("vestibulom", &SearchOptions::new().threshold(0.8)).unwrap().len(), 1);

Any character-level substitution whose similarity is below the floor is discarded immediately, before it can contribute to a score. A candidate that would need such a substitution simply isn’t produced.

What it applies to

  • Only character-level substitutions. Exact matches are unaffected (similarity 1.0), and explicit mappings carry their own scores and bypass the floor.
  • Independent of the threshold. The floor is a per-symbol gate; the threshold is a whole-match gate. A match must pass both.

When to use it

Reach for the floor when a wrong-but-diluted character would be a semantic error, not just a lower score — for instance in name/entity matching, where turning Petr into Pxtr should not count as a near-match no matter how long the surrounding name is. The default is 0.0 (no floor), preserving the purely additive behavior.