Algorithm Search⌘K

Proofs: String-matching automaton

These are the human proofs of String-matching automaton, at full length.

The string-matching automaton reports exactly the occurrences full

This proof shows: correctness, termination.

Claim. If δ[q][c]=σP(P[0…q−1] c)\delta[q][c] = \sigma_P(P[0 \ldots q-1]\,c) for every state 0≤q≤m0 \le q \le m and every character cc, then AUTOMATON-SEARCH(T,δ,m)(T, \delta, m) stops after n=∣T∣n = |T| steps and outputs exactly the shifts ss with T[s…s+m−1]=PT[s \ldots s+m-1] = P, in increasing order. That the construction produces this table is proved on the page of the construction.

Here σP(w)\sigma_P(w) is the length of the longest prefix of PP that is a suffix of ww. It is at most mm and at most ∣w∣|w|.

Lemma 1. For any string ww and character cc, σP(wc)≤σP(w)+1\sigma_P(wc) \le \sigma_P(w) + 1.

Proof. Let r=σP(wc)r = \sigma_P(wc). If r=0r = 0 there is nothing to show. Otherwise P[0…r−1]P[0 \ldots r-1] is a suffix of wcwc, so P[0…r−2]P[0 \ldots r-2] is a suffix of ww, and r−1≤σP(w)r - 1 \le \sigma_P(w). □\square

Lemma 2. If q=σP(w)q = \sigma_P(w), then σP(wc)=σP(P[0…q−1] c)\sigma_P(wc) = \sigma_P(P[0 \ldots q-1]\,c).

Proof. Let x=P[0…q−1]x = P[0 \ldots q-1], a suffix of ww, so xcxc is a suffix of wcwc. Any prefix of PP that is a suffix of xcxc is then a suffix of wcwc, so σP(xc)≤σP(wc)\sigma_P(xc) \le \sigma_P(wc). Conversely, let r=σP(wc)r = \sigma_P(wc). By Lemma 1, r≤q+1=∣xc∣r \le q + 1 = |xc|. The strings P[0…r−1]P[0 \ldots r-1] and xcxc are both suffixes of wcwc, and the first is not longer, so it is a suffix of xcxc. So r≤σP(xc)r \le \sigma_P(xc). □\square

Theorem. The claim holds.

Proof. Assume m≥1m \ge 1; for m=0m = 0, line L2 outputs all shifts 0,…,n0, \ldots, n, and each is valid because the empty string occurs everywhere. We show by induction on ii that after line L5 in the iteration for ii, q=σP(T[0…i])q = \sigma_P(T[0 \ldots i]). Before the loop, q=0=σPq = 0 = \sigma_P of the empty string. If q=σP(T[0…i−1])q = \sigma_P(T[0 \ldots i-1]) before line L5, then line L5 sets q=δ[q][T[i]]=σP(P[0…q−1] T[i])=σP(T[0…i])q = \delta[q][T[i]] = \sigma_P(P[0 \ldots q-1]\,T[i]) = \sigma_P(T[0 \ldots i]) by Lemma 2.

Now σP(T[0…i])=m\sigma_P(T[0 \ldots i]) = m exactly when PP is a suffix of T[0…i]T[0 \ldots i], that is, when T[i−m+1…i]=PT[i-m+1 \ldots i] = P. So line L7 outputs the shift s=i−m+1s = i - m + 1 exactly when it is valid. Each valid shift ss is output in the iteration i=s+m−1i = s + m - 1, and the shifts are output in increasing order of ii, hence of ss. When m>nm > n, the state never reaches mm, because σP(w)≤∣w∣<m\sigma_P(w) \le |w| < m. The loop has nn iterations of constant work, so the algorithm stops. ■\blacksquare

Back to String-matching automaton