Minimum Edit Distance
Much of language processing needs to measure how similar two strings are — a speller ranking corrections, a diff tool, a coreference resolver. Minimum edit distance counts the insertions, deletions, and substitutions that turn one string into another, computed by a dynamic-programming table.
╌╌╌╌
This builds on Regular Expressions and Text Normalization, which turned a raw character stream into clean tokens. That gave us strings to work with; this lesson gives us a way to compare two of them.
Measuring string similarity
Much of language processing needs to measure how similar two strings are. A speller
seeing graffe should rank giraffe (one insertion away) above grail (several
edits away). A coreference system, deciding whether Stanford President Marc Tessier-Lavigne
and Stanford University President Marc Tessier-Lavigne
name the
same person, uses the fact that the strings differ by a single word. Minimum edit distance quantifies both intuitions: it counts the
smallest number of one-character edits that turn one string into the other, so a small
distance means the strings are close.
The clearest way to see a distance is as an alignment — a correspondence between
the characters of the two strings, with a symbol under each column recording the
operation. For intention → execution, one minimum alignment uses five operations
(one deletion, three substitutions, one insertion); under the substitution-cost-2
Levenshtein it costs .
The dynamic-programming algorithm
How do we find the minimum? Naively, the space of edit sequences is enormous — but most sequences pass through the same intermediate strings, so the work collapses. That overlap is what dynamic programming exploits: solve the big problem by combining stored solutions to overlapping sub-problems. Minimum edit distance is one of the field's canonical DP algorithms, alongside Viterbi decoding and CKY parsing; if you have met DP in a string-algorithms course, this is the same table-driven method, applied to language.
Let be the source string of length and the target of length . Define as the edit distance between the first characters of and the first characters of . The answer is . The base cases are the distances from the empty string: turning characters into nothing takes deletions, so ; the reverse takes insertions, so . Each interior cell is the cheapest of the three moves that reach it — a deletion from above, an insertion from the left, or a substitution (or match) from the diagonal:
The three cases are the three ways the last characters can be handled:
- Deletion: align 's first characters against all of 's, then delete
- Insertion: align all against the first , then insert
- Substitution or match: align the first against the first , then substitute for , or pay nothing if they already match
The cell keeps the cheapest of the three.
Under the Levenshtein weighting — insertion and deletion cost , a substitution costs except that matching a letter to itself is free — this specializes to
Fill the table row by row from the bottom-left corner: initialize the border, then sweep every interior cell, taking the running minimum.
- 1input: source string , target string
- 2length of
- 3length of
- 4create a distance matrix
- 5
- 6for to do
- 7an empty target: delete every source char
- 8for to do
- 9an empty source: insert every target char
- 10for to do
- 11for to do
- 12
- 13return
A worked table
For and under the substitution-cost-2 Levenshtein, the completed matrix reads in the top-right corner. The source runs up the left edge, the target across the bottom; each cell holds the minimum edit distance between the two prefixes meeting at it.
The backtrace
The distance alone gives the cost of the best alignment; with one extra bookkeeping step, the same table also recovers the alignment itself. While filling the matrix, store in each cell a backpointer to the neighbor (or neighbors) that supplied its minimum: a left arrow for an insertion, a down arrow for a deletion, a diagonal for a substitution or match. After the table is full, backtrace from the top-right cell, following pointers back to the origin. The path of cells you walk is a minimum-cost alignment — a diagonal step aligns two characters, a horizontal step is an insertion, a vertical step a deletion.
Walk the intention → execution table concretely. Starting from the answer cell
, at each step you look at the three neighbors that could have produced the
cell and step to whichever one the recurrence used. The path recovered is a diagonal
at every column except one deletion near the start and one insertion in the middle,
and reading the operations off the path in source order gives:
Adjusting for the one deletion and one insertion in the full alignment, the operation
tally is one deletion, one insertion, and three substitutions that touch distinct
characters, plus four free matches on the shared suffix tion. Under the
substitution-cost-2 weighting that is , matching the corner
cell exactly. The alignment is what a downstream task consumes: a speller uses it to
say which letters to change, and a diff tool uses the same path to show insertions
and deletions between two files.
Drawn on the real matrix, the path is not the schematic diagonal but a concrete
staircase through the actual cells. It leaves the answer , walks the free
suffix tion straight down the diagonal at constant cost , drops one cell for the
substitution, takes one horizontal insertion of c, matches e, then two
substitutions and a single vertical deletion of the leading i land it at the origin.
Each arrow points from a cell to the predecessor that supplied its minimum, so the
whole path is read from top-right to bottom-left; reversing it recovers the edit
sequence in source order.
That extra step generalizes. Allow arbitrary operation costs — say, cheaper
substitutions between letters adjacent on a keyboard — and the same table becomes a
spelling-correction engine. Replace minimum cost
with maximum probability
and the
recurrence becomes the Viterbi algorithm, used throughout sequence labeling and
speech recognition. The DP table filled for intention → execution is the same
machinery, reused across the subject.1
Weighted edits and the cost of the alignment
The Levenshtein weighting charges every substitution the same, but the framework
does not require it. Replace the constant sub-cost with a per-pair cost — a
confusion matrix — and the same table computes a distance tuned to a real error
model. For spelling correction the natural costs come from how often one letter is
mistyped for another: substituting e for a (adjacent readings, common
typo) should cost less than substituting e for q. For biological sequence
alignment the costs come from substitution matrices estimated from evolution, and the
identical DP, run with a gap penalty and those costs, is the Needleman–Wunsch
algorithm. Nothing in the recurrence changes; only the three cost functions do. This
is why edit distance is a template rather than a single algorithm: fix the costs and
you fix the notion of similar.
Footnotes
- Jurafsky & Martin, §2.5 — Minimum Edit Distance: the Levenshtein distance, the dynamic-programming recurrence and algorithm, the intention/execution worked table, and the backtrace that recovers an alignment. The generalization with per-pair costs and gap penalties is Needleman & Wunsch,
A general method applicable to the search for similarities in the amino acid sequence of two proteins,
Journal of Molecular Biology 48 (1970). ↩
╌╌ END ╌╌