Algorithm Search⌘K

Proofs: Morris-Pratt algorithm

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

Morris-Pratt 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, MP-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 every shift 0,…,n0, \ldots, n, as the definition requires.

Setup. Assume that lines L12 to L18 compute the prefix function π\pi of PP; the proof is on that page. For a string xx, let λ(x)\lambda(x) be the length of the longest prefix of PP that is a suffix of xx and is shorter than mm. We use the border-chain lemma: for q≥1q \ge 1, the lengths of the proper borders of P[0…q−1]P[0 \ldots q-1] are exactly π[q−1],π[π[q−1]−1],…,0\pi[q-1], \pi[\pi[q-1]-1], \ldots, 0, in decreasing order.

Lemma 1. Let q=λ(x)q = \lambda(x). The prefixes of PP of length at most qq that are suffixes of xx are exactly P[0…q−1]P[0 \ldots q-1] and the proper borders of P[0…q−1]P[0 \ldots q-1].

Proof. If k≤qk \le q and P[0…k−1]P[0 \ldots k-1] is a suffix of xx, then it is a suffix of the longer suffix P[0…q−1]P[0 \ldots q-1] of xx, and it is a prefix of it too, so it is a border of P[0…q−1]P[0 \ldots q-1] (proper if k<qk < q). Conversely, a border of P[0…q−1]P[0 \ldots q-1] is a suffix of P[0…q−1]P[0 \ldots q-1], hence of xx. □\square

Lemma 2. Let q=λ(x)q = \lambda(x) at line L6 and c=T[i]c = T[i]. After line L8, qq is the length ℓ\ell of the longest prefix of PP that is a suffix of xcxc.

Proof. For j<mj < m, the prefix P[0…j]P[0 \ldots j] 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. Such a jj is at most λ(x)=q\lambda(x) = q. So by Lemma 1, ℓ−1\ell - 1 is the first value jj in the list q,π[q−1],π[π[q−1]−1],…,0q, \pi[q-1], \pi[\pi[q-1]-1], \ldots, 0 with P[j]=cP[j] = c, and ℓ=0\ell = 0 if there is none.

Lines L6 and L7 walk down this list, in this order, while the current value is positive and P[q]≠cP[q] \ne c. Each step lowers qq by at least 1 and q≥0q \ge 0, so the loop stops. If it stops with P[q]=cP[q] = c, qq is the first good value and line L8 sets q=ℓq = \ell. If it stops with q=0q = 0 and P[0]≠cP[0] \ne c, no value of the list is good, line L8 changes nothing, and q=0=ℓq = 0 = \ell. □\square

Theorem. The claim holds.

Proof. We prove 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 is the increasing list of the valid shifts ss with s+m≤is + m \le i.

For i=0i = 0, line L4 sets q=0=λq = 0 = \lambda of the empty string, and nothing is output. Assume (I) for ii. By Lemma 2, after line L8, q=ℓq = \ell, the length of the longest prefix of PP that is a suffix of T[0…i]T[0 \ldots i]. The shift i−m+1i - m + 1 is valid exactly when ℓ=m\ell = m, and it is larger than all shifts output before, so lines L9 and L10 keep the second part of (I). If ℓ<m\ell < m, then q=λ(T[0…i])q = \lambda(T[0 \ldots i]). If ℓ=m\ell = m, the longest prefix shorter than mm that is a suffix of T[0…i]T[0 \ldots i] is, by Lemma 1 applied with PP in place of P[0…q−1]P[0 \ldots q-1], the longest proper border of PP, of length π[m−1]\pi[m-1], which line L11 assigns. So (I) holds for i+1i + 1. The loop of line L5 runs nn times and each inner loop stops, so the algorithm stops, and (I) for i=ni = n is the claim. ■\blacksquare

Back to Morris-Pratt algorithm