String similarity - Levenshtein distance
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Levenshtein distance measures how many single-character edits are required to transform one string into another. It is one of the most useful baseline metrics for spelling correction, fuzzy matching, deduplication, and search, because it turns a vague idea of "similar text" into a concrete edit count.
What the Distance Counts
The standard Levenshtein metric allows three operations:
- insert one character
- delete one character
- substitute one character
So the distance between kitten and sitting is 3:
- substitute
kwiths - substitute
ewithi - insert
g
A smaller distance means the strings are closer. A distance of 0 means the strings are identical.
Dynamic Programming Solution
The classic algorithm builds a matrix where each cell stores the minimum edit count for prefixes of the two strings. That avoids the exponential blowup of naive recursion.
A space-efficient Python implementation keeps only one row at a time:
This runs in O(mn) time and O(min(m, n)) extra space.
Distance Versus Similarity Score
Levenshtein distance is a difference measure, not a similarity percentage. If you want a normalized similarity score, convert it explicitly.
This is useful when comparing strings of different lengths, because a raw distance of 2 means something very different for strings of length 4 versus length 40.
Where It Works Well
Levenshtein distance is good when edits are local and characters matter directly. Typical use cases include:
- spell checking and autocomplete fallback
- matching user-entered names with minor typos
- ranking near-duplicate identifiers
- approximate matching in small dictionaries
It is especially useful as a baseline because it is easy to explain and easy to test.
Where It Falls Short
Not all similarity problems are edit-distance problems.
If adjacent transpositions should count as one error, standard Levenshtein may be too strict. In that case, Damerau-Levenshtein is often a better fit.
If token order, phonetics, or meaning matter more than character edits, other techniques may outperform it entirely. For example, comparing full names, sentences, or product titles often benefits from token-based or embedding-based methods.
Unicode and Preprocessing Matter
Text that looks identical to users may have different Unicode representations. Before measuring distance, normalize the strings and decide whether case, accents, whitespace, or punctuation should matter.
Without preprocessing, your metric may be correct technically and still wrong for the business problem.
Common Pitfalls
A common mistake is using raw distance as if it were already a similarity percentage. Distance 2 is not inherently "good" or "bad" without context.
Another mistake is applying Levenshtein to long strings where semantic similarity matters more than character edits. It becomes expensive and often less meaningful.
Developers also forget normalization, which leads to misleading differences caused by case, whitespace, or Unicode composition rather than real content changes.
Summary
- Levenshtein distance counts insertions, deletions, and substitutions.
- Dynamic programming computes it efficiently in
O(mn)time. - Normalize the result if you need a similarity score instead of an edit count.
- It works well for typos and short fuzzy matches, not for every text problem.
- Preprocessing and Unicode normalization are often just as important as the distance formula itself.
Related reading

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.