String similarity score/hash
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
String similarity scoring quantifies how alike two strings are, returning a value between 0 (completely different) and 1 (identical). Common approaches include edit distance (Levenshtein), token-based similarity (Jaccard, cosine), phonetic matching (Soundex, Metaphone), and hash-based techniques (SimHash, MinHash). The right choice depends on whether you need exact character matching, semantic similarity, or fuzzy deduplication at scale.
Levenshtein Distance (Edit Distance)
The minimum number of single-character edits (insert, delete, substitute) to transform one string into another:
Python's difflib (Built-In)
SequenceMatcher uses the Ratcliff/Obershelp algorithm — it finds the longest common subsequences and computes a ratio based on matched characters.
Jaccard Similarity (Token-Based)
Compares sets of tokens (words, n-grams) rather than characters:
Jaccard is good for comparing documents or sentences where word order does not matter.
Cosine Similarity (TF Vectors)
Treats strings as vectors of term frequencies and measures the angle between them:
SimHash (Locality-Sensitive Hashing)
SimHash creates a fingerprint where similar strings produce similar hashes. Two strings' similarity is estimated by comparing their hash bits:
SimHash is used by Google for web page deduplication — it scales to billions of documents.
Soundex (Phonetic Matching)
Matches strings that sound alike in English:
Using Libraries
Comparison Table
| Method | Type | Best For | Time Complexity |
| Levenshtein | Character | Typo detection, spell check | O(n*m) |
| Jaro-Winkler | Character | Name matching | O(n*m) |
| Jaccard | Token | Document comparison | O(n+m) |
| Cosine | Token | Text similarity | O(n+m) |
| SimHash | Hash | Large-scale deduplication | O(n) per doc |
| Soundex | Phonetic | Name matching (English) | O(n) |
| Metaphone | Phonetic | Name matching (improved) | O(n) |
Common Pitfalls
- Case sensitivity: Most similarity functions are case-sensitive by default.
"Hello"and"hello"score less than 1.0. Normalize case before comparing. - Levenshtein on long strings: O(n*m) time and space. For strings over 10,000 characters, use approximate methods or n-gram hashing instead.
- Jaccard ignoring word frequency: Jaccard treats each word as present or absent.
"the the the cat"and"the cat"have Jaccard similarity 1.0. Use cosine similarity when word frequency matters. - SimHash for short strings: SimHash works well for documents but poorly for short strings (fewer than 5 tokens) because the hash bits are not sufficiently populated.
- Soundex is English-only: Soundex encoding is designed for English names. It produces meaningless results for other languages. Use language-specific phonetic algorithms (Cologne phonetics for German, etc.).
Summary
- Use Levenshtein/
difflib.SequenceMatcherfor character-level typo detection - Use Jaccard or cosine similarity for document/sentence comparison
- Use SimHash or MinHash for large-scale near-duplicate detection
- Use Soundex or Metaphone for phonetic (sounds-like) matching
- Use
thefuzz(fuzzywuzzy) for practical fuzzy string matching with multiple strategies - Always normalize case and whitespace before comparing strings
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.