Foundations/Minimum Edit Distance

Lesson 1.31,252 words

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 intentionexecution, one minimum alignment uses five operations (one deletion, three substitutions, one insertion); under the substitution-cost-2 Levenshtein it costs .

An alignment of intention (top) with execution (bottom). Each column is one operation: d deletes, s substitutes, i inserts; a blank is a gap. The operation row spells out one minimum-cost edit sequence.

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.

Algorithm:Min-Edit-Distance(X,Y)\textsc{Min-Edit-Distance}(X, Y) — edit distance by dynamic programming
  1. 1
    input: source string XX, target string YY
  2. 2
    nn \gets length of XX
  3. 3
    mm \gets length of YY
  4. 4
    create a distance matrix D[0n,0m]D[0 \ldots n,\, 0 \ldots m]
  5. 5
    D[0,0]0D[0,0] \gets 0
  6. 6
    for i=1i = 1 to nn do
  7. 7
    D[i,0]D[i1,0]+del-cost(X[i])D[i,0] \gets D[i-1,0] + \text{del-cost}(X[i])
    an empty target: delete every source char
  8. 8
    for j=1j = 1 to mm do
  9. 9
    D[0,j]D[0,j1]+ins-cost(Y[j])D[0,j] \gets D[0,j-1] + \text{ins-cost}(Y[j])
    an empty source: insert every target char
  10. 10
    for i=1i = 1 to nn do
  11. 11
    for j=1j = 1 to mm do
  12. 12
    D[i,j]min(D[i1,j]+del-cost(X[i]), D[i1,j1]+sub-cost(X[i],Y[j]), D[i,j1]+ins-cost(Y[j]))D[i,j] \gets \min\bigl(D[i-1,j] + \text{del-cost}(X[i]),\ D[i-1,j-1] + \text{sub-cost}(X[i], Y[j]),\ D[i,j-1] + \text{ins-cost}(Y[j])\bigr)
  13. 13
    return D[n,m]D[n,m]

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 dynamic-programming matrix for the edit distance between intention (source, left edge, read bottom to top) and execution (target, bottom edge), with insertion and deletion cost 1 and substitution cost 2. The answer, 8, sits in the top-right cell.

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.

The backtrace over the edit-distance matrix. From the answer cell (top right) each arrow points at a predecessor that achieved the minimum; a diagonal aligns or substitutes, a horizontal inserts, a vertical deletes. One path back to the origin is a minimum-cost alignment.

Walk the intentionexecution 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.

The minimum-cost backtrace traced on the real intention-to-execution matrix. From the answer cell 8 (top right) each arrow points to the predecessor that achieved the minimum; the highlighted cells are the optimal alignment. Four diagonal matches down the shared suffix tion, one diagonal substitution n to u, one horizontal insertion of c, one diagonal match e, two more substitutions, and one vertical deletion of the leading i reach the origin at total cost 8.

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 intentionexecution 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

  1. 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 ╌╌