Algorithm Search⌘K

Proofs: Levenshtein automaton

These are the human proofs of Levenshtein automaton, at full length.

The capped rows form a deterministic automaton for the words within distance k full

This proof shows: correctness.

Indices are 0-based. Fix a word WW of length mm and k≥0k \ge 0, and let K=k+1K = k + 1. For a string xx let Dx[i]=ed⁡(W[0..i),x)D_x[i] = \operatorname{ed}(W[0..i), x) for 0≤i≤m0 \le i \le m, in the Levenshtein model with unit costs, and let Rx[i]=min⁡(Dx[i],K)R_x[i] = \min(D_x[i], K) be the capped row. For a row RR and a symbol cc let step⁡(R,c)\operatorname{step}(R, c) be the row R′R' of lines L3 to L5: R′[0]=min⁡(R[0]+1,K)R'[0] = \min(R[0] + 1, K) and R′[i]=min⁡(R[i−1]+[W[i−1]≠c], R[i]+1, R′[i−1]+1, K)R'[i] = \min(R[i-1] + [W[i-1] \ne c],\ R[i] + 1,\ R'[i-1] + 1,\ K) for 1≤i≤m1 \le i \le m.

Lemma 1 (the uncapped step). For each string xx and symbol cc, Dxc[0]=Dx[0]+1D_{xc}[0] = D_x[0] + 1 and, for 1≤i≤m1 \le i \le m,

Dxc[i]=min⁡(Dx[i−1]+[W[i−1]≠c], Dx[i]+1, Dxc[i−1]+1).D_{xc}[i] = \min\bigl(D_x[i-1] + [W[i-1] \ne c],\ D_x[i] + 1,\ D_{xc}[i-1] + 1\bigr).

Proof. Dx[i]D_x[i] is the entry in row ii and column ∣x∣|x| of the Wagner-Fischer table of WW and xx, and appending cc to xx adds one column. The first line is ed⁡(ε,xc)=∣x∣+1\operatorname{ed}(\varepsilon, xc) = |x| + 1, and the second is the Wagner-Fischer recurrence for the new column, whose correctness is proved on that page. □\square

Lemma 2 (capping commutes with the step). For every string xx and symbol cc, step⁡(Rx,c)=Rxc\operatorname{step}(R_x, c) = R_{xc}.

Proof. For integers a≥0a \ge 0 and d≥0d \ge 0, min⁡(min⁡(a,K)+d,K)=min⁡(a+d,K)\min(\min(a, K) + d, K) = \min(a + d, K): if a≥Ka \ge K both sides are KK, and else they are equal. Also min⁡(min⁡(a,K),min⁡(b,K))=min⁡(a,b,K)\min(\min(a, K), \min(b, K)) = \min(a, b, K). Induction on ii: R′[0]=min⁡(min⁡(Dx[0],K)+1,K)=min⁡(Dx[0]+1,K)=Rxc[0]R'[0] = \min(\min(D_x[0], K) + 1, K) = \min(D_x[0] + 1, K) = R_{xc}[0] by Lemma 1. For i≥1i \ge 1, assume R′[i−1]=min⁡(Dxc[i−1],K)R'[i-1] = \min(D_{xc}[i-1], K). Each of the three terms in line L5 has the form min⁡(a,K)+d\min(a, K) + d with d∈{0,1}d \in \{0, 1\}, where aa is the matching term of Lemma 1. Taking the minimum with KK and using the two identities gives R′[i]=min⁡(Dxc[i],K)=Rxc[i]R'[i] = \min(D_{xc}[i], K) = R_{xc}[i]. □\square

Theorem 1 (the automaton). Let the states be the capped rows, the start state RεR_\varepsilon with Rε[i]=min⁡(i,K)R_\varepsilon[i] = \min(i, K), the transition step⁡\operatorname{step}, and the accepting states the rows with R[m]≤kR[m] \le k. Then the state after reading xx is RxR_x, and the automaton accepts xx exactly when ed⁡(W,x)≤k\operatorname{ed}(W, x) \le k.

Proof. Dε[i]=iD_\varepsilon[i] = i, so the start state is RεR_\varepsilon (line L2). By Lemma 2 and induction on ∣x∣|x|, the state after xx is RxR_x. It is accepting exactly when min⁡(ed⁡(W,x),K)≤k\min(\operatorname{ed}(W, x), K) \le k, that is, when ed⁡(W,x)≤k\operatorname{ed}(W, x) \le k (line L7). Lines L6 and the memo table only give each distinct row one id, which does not change the function from inputs to rows. □\square

Lemma 3 (the dead state). min⁡iRx[i]≤k\min_i R_x[i] \le k exactly when some string yy has ed⁡(W,xy)≤k\operatorname{ed}(W, xy) \le k.

Proof. Suppose Rx[i]≤kR_x[i] \le k for some ii. Let y=W[i..m)y = W[i..m). An alignment of W[0..i)W[0..i) with xx of cost Dx[i]D_x[i], followed by m−im - i matches, aligns WW with xyxy, so ed⁡(W,xy)≤Dx[i]≤k\operatorname{ed}(W, xy) \le D_x[i] \le k. Conversely, suppose all entries of RxR_x equal KK. Then step⁡\operatorname{step} gives R′[0]=min⁡(K+1,K)=KR'[0] = \min(K + 1, K) = K, and by induction on ii each term of line L5 is at least KK, so R′[i]=KR'[i] = K. So the row of all KK maps to itself on every symbol, and it is not accepting. By Theorem 1, no extension xyxy has ed⁡(W,xy)≤k\operatorname{ed}(W, xy) \le k. □\square

So line L8 returns false exactly for the dead state, and the walk of lines L9 to L12 loses no answer when it drops a trie node whose state is dead: every word below that node extends the string of the node.

Theorem 2 (the lookup). LOOKUP reports each word yy of the dictionary with ed⁡(W,y)≤k\operatorname{ed}(W, y) \le k exactly once, and no other word.

Proof. The trie has one node for each prefix of a dictionary word, and a node is marked when its string is a word. Each entry (u,R)(u, R) pushed on the stack has R=RyR = R_y for the string yy of node uu: this holds for the root with RεR_\varepsilon, and line L12 pushes the child vv of uu by symbol cc with step⁡(Ry,c)=Ryc\operatorname{step}(R_y, c) = R_{yc} by Lemma 2. Each node is pushed at most once, because it has one parent. Line L11 reports yy exactly when uu is marked and Ry[m]≤kR_y[m] \le k, so every report is correct by Theorem 1 and no word is reported twice. For completeness, let yy be a word with ed⁡(W,y)≤k\operatorname{ed}(W, y) \le k. For each prefix y′y' of yy, yy extends y′y', so Ry′R_{y'} is not dead by Lemma 3, and line L12 pushes the node of y′y' when it pops its parent. By induction on the length of the prefix, the node of yy is pushed and popped, and line L11 reports yy. □\square

Search mode. In search mode line L3 sets R′[0]=0R'[0] = 0. With Dx[i]=C[i][∣x∣]D_x[i] = C[i][|x|], the column of the Sellers table of WW against the text xx, Lemma 1 holds with Dxc[0]=0D_{xc}[0] = 0 in place of Dx[0]+1D_x[0] + 1, by the Sellers recurrence, and the proof of Lemma 2 goes through unchanged for i≥1i \ge 1. So after reading T[0..j)T[0..j) the state is the capped column jj, and it is accepting exactly when C[m][j]≤kC[m][j] \le k, which is the condition for the end position jj proved on the Sellers page.

Theorem 3 (the number of states). The automaton has at most (m+k+1)(k+2) 32k+1(m + k + 1)(k + 2)\,3^{2k} + 1 reachable states.

Proof. Let L=∣x∣L = |x|. Each alignment of W[0..i)W[0..i) with xx needs at least ∣i−L∣|i - L| insertions or deletions, so Dx[i]≥∣i−L∣D_x[i] \ge |i - L|. If L≥m+KL \ge m + K, then every i≤mi \le m has ∣i−L∣≥K|i - L| \ge K, so RxR_x is the dead row. Else 0≤L≤m+k0 \le L \le m + k. For ∣i−L∣>k|i - L| > k the entry Rx[i]R_x[i] is KK, so RxR_x is fixed by LL and the entries with ii in the window {L−k,…,L+k}∩{0,…,m}\{L - k, \ldots, L + k\} \cap \{0, \ldots, m\}, which has at most 2k+12k + 1 indices. Deleting W[i−1]W[i-1] turns an alignment of W[0..i)W[0..i) with xx into one of W[0..i−1)W[0..i-1) with xx at one more unit of cost, and the reverse insertion works the same way, so ∣Dx[i]−Dx[i−1]∣≤1|D_x[i] - D_x[i-1]| \le 1. Capping keeps this bound, since a↦min⁡(a,K)a \mapsto \min(a, K) does not increase distances between integers. So the window is fixed by its first entry, one of the k+2k + 2 values 00 to KK, and at most 2k2k differences in {−1,0,1}\{-1, 0, 1\}. This gives at most (k+2) 32k(k + 2)\,3^{2k} rows for each of the m+k+1m + k + 1 values of LL, plus the dead row. ■\blacksquare

Back to Levenshtein automaton