Algorithm Search⌘K

Proofs: Knuth-Morris-Pratt algorithm

These are the human proofs of Knuth-Morris-Pratt algorithm, at full length.

KMP outputs exactly the valid shifts full

This proof shows: correctness, termination.

Claim. For a text T[0…n−1]T[0 \ldots n-1] and a pattern P[0…m−1]P[0 \ldots m-1] with m≥1m \ge 1, KMP-MATCHER(T,P)(T, P) stops and outputs exactly the shifts ss, 0≤s≤n−m0 \le s \le n - m, with T[s…s+m−1]=PT[s \ldots s+m-1] = P, in increasing order. (For m=0m = 0, line L2 outputs all shifts 0,…,n0, \ldots, n, which is the definition.)

Setup. For a string xx, let λ(x)\lambda(x) be the length of the longest prefix of PP that is a suffix of xx and has length less than mm. Let π\pi be the prefix function of PP. We use two facts proved on that page.

  • (F1) The borders of P[0…q−1]P[0 \ldots q-1], for q≥1q \ge 1, have the lengths π[q−1],π[π[q−1]−1],…,0\pi[q-1], \pi[\pi[q-1]-1], \ldots, 0, and no other lengths.
  • (F2) A border of a border of xx is a border of xx, and a border of xx shorter than another border uu of xx is a border of uu.

Lemma 1 (the table). For 1≤q<m1 \le q < m, line L16 sets nxt[q]\mathrm{nxt}[q] to the largest k<qk < q such that P[0…k−1]P[0 \ldots k-1] is a border of P[0…q−1]P[0 \ldots q-1] and P[k]≠P[q]P[k] \ne P[q], or to −1-1 if there is none. Also nxt[0]=−1\mathrm{nxt}[0] = -1, which is the same rule for q=0q = 0 (no k<0k < 0 exists).

Proof. By strong induction on qq. Let k=π[q−1]<qk = \pi[q-1] < q, the longest proper border length of P[0…q−1]P[0 \ldots q-1]. If P[k]≠P[q]P[k] \ne P[q], then kk is the largest candidate, and line L16 sets nxt[q]=k\mathrm{nxt}[q] = k. If P[k]=P[q]P[k] = P[q], then kk is not a candidate, and by (F1) and (F2) the remaining candidates are exactly the lengths j<kj < k such that P[0…j−1]P[0 \ldots j-1] is a border of P[0…k−1]P[0 \ldots k-1] and P[j]≠P[q]=P[k]P[j] \ne P[q] = P[k]. By the induction hypothesis for k<qk < q, the largest of them is nxt[k]\mathrm{nxt}[k], or −1-1 if there is none. □\square

Lemma 2 (one text character). Let xx be a string, cc a character, and q=λ(x)q = \lambda(x). Run lines L6 to L8 with this qq and T[i]=cT[i] = c. Then they stop, and afterwards $q = $ the length of the longest prefix of PP that is a suffix of xcxc (this length may be mm).

Proof. Let BB be the set of lengths kk with 0≤k≤q0 \le k \le q such that P[0…k−1]P[0 \ldots k-1] is a suffix of xx. A prefix P[0…j]P[0 \ldots j] with j<mj < m is a suffix of xcxc exactly when P[0…j−1]P[0 \ldots j-1] is a suffix of xx and P[j]=cP[j] = c. Each such jj satisfies j≤qj \le q by the definition of q=λ(x)q = \lambda(x), so j∈Bj \in B. And for k≤qk \le q, P[0…k−1]P[0 \ldots k-1] is a suffix of xx exactly when it is a border of P[0…q−1]P[0 \ldots q-1] or equal to it, by (F2) applied to the suffixes of xx. So the answer is 1+max⁡{ j∈B:P[j]=c }1 + \max\{\, j \in B : P[j] = c \,\}, or 00 if that set is empty.

The loop of line L6 keeps the invariant: q=−1q = -1, or q∈Bq \in B and no j∈Bj \in B with j>qj > q has P[j]=cP[j] = c. It holds at the start. If q≥0q \ge 0 and P[q]≠cP[q] \ne c, line L7 sets qq to nxt[q]\mathrm{nxt}[q]. By Lemma 1, each j∈Bj \in B with nxt[q]<j<q\mathrm{nxt}[q] < j < q has P[j]=P[q]≠cP[j] = P[q] \ne c, so the invariant holds for the new value. Each pass decreases qq by at least 1 and q≥−1q \ge -1, so the loop stops after at most q+1q + 1 passes. At the exit, either q≥0q \ge 0 and P[q]=cP[q] = c, so qq is the largest j∈Bj \in B with P[j]=cP[j] = c, or q=−1q = -1 and no j∈Bj \in B has P[j]=cP[j] = c. Line L8 adds 1, which gives the answer in both cases. □\square

Theorem. The claim holds.

Proof. We show by induction on ii that at the start of the iteration for ii (and at the end, for i=ni = n):

(I) q=λ(T[0…i−1])q = \lambda(T[0 \ldots i-1]), and the output so far is the increasing list of valid shifts ss with s+m−1<is + m - 1 < i.

Initialization. For i=0i = 0, the text read is empty, λ\lambda of the empty string is 0, and nothing is output, so (I) holds after line L4.

Maintenance. Assume (I) for ii. By Lemma 2, after line L8, qq is the length ℓ\ell of the longest prefix of PP that is a suffix of T[0…i]T[0 \ldots i]. A valid shift ends at ii exactly when PP itself is a suffix of T[0…i]T[0 \ldots i], that is when ℓ=m\ell = m, and then the shift is i−m+1i - m + 1, larger than all earlier outputs. So lines L9 and L10 output exactly the valid shift that ends at ii, if any. If ℓ<m\ell < m, then q=ℓ=λ(T[0…i])q = \ell = \lambda(T[0 \ldots i]). If ℓ=m\ell = m, the longest prefix of PP shorter than mm that is a suffix of T[0…i]T[0 \ldots i] is the longest proper border of PP, by (F2), whose length is π[m−1]=nxt[m]\pi[m-1] = \mathrm{nxt}[m], the value set by line L11. In both cases (I) holds for i+1i + 1.

Termination. The loop of line L5 runs nn times, and each inner loop stops by Lemma 2. At the end, (I) for i=ni = n says that the output is the increasing list of all valid shifts. ■\blacksquare

Cost. The proof of Lemma 2 shows that each pass of line L7 decreases qq by at least 1. The complexity section of the page turns this into the bound of 2n2n comparisons.

Back to Knuth-Morris-Pratt algorithm