Algorithm Search⌘K

Proofs: Apostolico-Giancarlo algorithm

These are the human proofs of Apostolico-Giancarlo algorithm, at full length.

Apostolico-Giancarlo 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], APOSTOLICO-GIANCARLO(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, which is correct, so let m≥1m \ge 1. We take as given the tables of the page: suff[i]\mathrm{suff}[i] is the largest h≤i+1h \le i + 1 with P[i−h+1…i]=P[m−h…m−1]P[i-h+1 \ldots i] = P[m-h \ldots m-1], λ(c)\lambda(c) is the last position of cc in PP or −1-1, and gs\mathrm{gs} is the strong good-suffix table. That GOOD-SUFFIX computes gs\mathrm{gs}, that gs[0]\mathrm{gs}[0] is the smallest period of PP, and that the shift of lines L13 and L14 skips no valid shift, is proved on the page of Boyer-Moore (its Lemma 2), for a mismatch at a position ii with P[i]≠T[s+i]P[i] \ne T[s+i] and P[i+1…m−1]=T[s+i+1…s+m−1]P[i+1 \ldots m-1] = T[s+i+1 \ldots s+m-1].

For a text position tt, let ms(t)\mathrm{ms}(t) be the largest k≤min⁡(m,t+1)k \le \min(m, t + 1) with T[t−k+1…t]=P[m−k…m−1]T[t-k+1 \ldots t] = P[m-k \ldots m-1]: the length of the longest suffix of PP that ends at tt.

Invariant (I). At the start of each window ss, every entry skip[t]\mathrm{skip}[t] with s≤t≤s+m−1s \le t \le s + m - 1 is either 0 or equal to ms(t)\mathrm{ms}(t), and in the second case ms(t)>0\mathrm{ms}(t) > 0. (With the array indexed by t mod mt \bmod m, this is the statement about the entry read for tt.)

Initially all entries are 0. Entries are written only at line L13 or L14 for t=s+m−1t = s + m - 1; entries for positions that leave the window are cleared at line L15 before a new position with the same residue enters, because the positions entering, s+m,…,s+shift+m−1s + m, \ldots, s + \mathit{shift} + m - 1, have the same residues as the cleared s,…,s+min⁡(shift,m)−1s, \ldots, s + \min(\mathit{shift}, m) - 1 (all residues if shift≥m\mathit{shift} \ge m). So (I) holds if each written value equals ms(s+m−1)\mathrm{ms}(s + m - 1) and is positive or 0; we prove this in Lemma 2.

Lemma 1 (the scan). Assume (I) at window ss. The loop of lines L7 to L12 keeps the invariant T[s+i+1…s+m−1]=P[i+1…m−1]T[s+i+1 \ldots s+m-1] = P[i+1 \ldots m-1] and ends either with i=−1i = -1, when ss is valid, or with 0≤i<m0 \le i < m and T[s+i]≠P[i]T[s+i] \ne P[i].

Proof. The invariant holds at i=m−1i = m - 1. Consider one step at position ii, with k=skip[s+i]k = \mathrm{skip}[s+i] and h=suff[i]h = \mathrm{suff}[i].

If k=0k = 0, line L12 compares P[i]P[i] with T[s+i]T[s+i] and either extends the invariant by one position or ends with a mismatch at ii.

If k>0k > 0, then k=ms(s+i)k = \mathrm{ms}(s+i) by (I), so T[s+i−k+1…s+i]=P[m−k…m−1]T[s+i-k+1 \ldots s+i] = P[m-k \ldots m-1], and if k<mk < m and s+i−k≥0s + i - k \ge 0, then T[s+i−k]≠P[m−1−k]T[s+i-k] \ne P[m-1-k] by maximality. Also P[i−h+1…i]=P[m−h…m−1]P[i-h+1 \ldots i] = P[m-h \ldots m-1], and if h≤ih \le i then P[i−h]≠P[m−1−h]P[i-h] \ne P[m-1-h] by maximality.

  • Case k>hk > h, h=i+1h = i + 1. Then T[s…s+i]=P[m−1−i…m−1]T[s \ldots s+i] = P[m-1-i \ldots m-1], because k≥i+2>i+1k \ge i + 2 > i + 1 and the suffixes of length i+1=hi + 1 = h agree, and P[m−1−i…m−1]=P[0…i]P[m-1-i \ldots m-1] = P[0 \ldots i] because h=i+1h = i + 1. With the invariant, the window is an occurrence, and line L10 sets i=−1i = -1.
  • Case k>hk > h, h≤ih \le i. The text and P[0…i]P[0 \ldots i] both end with the suffix of PP of length hh, so T[s+i−h+1…s+i]=P[i−h+1…i]T[s+i-h+1 \ldots s+i] = P[i-h+1 \ldots i]. At position i−hi - h: since k>hk > h, T[s+i−h]=P[m−1−h]T[s+i-h] = P[m-1-h], while P[i−h]≠P[m−1−h]P[i-h] \ne P[m-1-h]. So the invariant holds down to i−h+1i - h + 1, and i−hi - h is a mismatch.
  • Case k<hk < h. Both end with the suffix of length kk, so the text matches P[i−k+1…i]P[i-k+1 \ldots i]. At position i−k≥0i - k \ge 0 (since k<h≤i+1k < h \le i + 1): since h>kh > k, P[i−k]=P[m−1−k]P[i-k] = P[m-1-k]; and k<h≤mk < h \le m with s+i−k≥0s + i - k \ge 0, so T[s+i−k]≠P[m−1−k]T[s+i-k] \ne P[m-1-k]. So i−ki - k is a mismatch.
  • Case k=hk = h. The text matches P[i−k+1…i]P[i-k+1 \ldots i], and line L11 sets i←i−ki \leftarrow i - k and goes on, which keeps the invariant.

Each step decreases ii or ends the loop, so the loop stops. □\square

Lemma 2 (the note). The value written at line L13 or L14 is ms(s+m−1)\mathrm{ms}(s + m - 1).

Proof. At line L13 the window is an occurrence, so ms(s+m−1)=m\mathrm{ms}(s+m-1) = m. At line L14, by Lemma 1, T[s+i+1…s+m−1]=P[i+1…m−1]T[s+i+1 \ldots s+m-1] = P[i+1 \ldots m-1] and T[s+i]≠P[i]T[s+i] \ne P[i], so the longest suffix of PP ending at s+m−1s + m - 1 has length exactly m−1−im - 1 - i. □\square

Proof of the claim. By Lemma 2, (I) holds at every window. By Lemma 1, line L13 outputs ss exactly when ss is valid, and otherwise line L14 runs with a true mismatch at ii and the text matching P[i+1…m−1]P[i+1 \ldots m-1], which is the situation of Boyer-Moore; its shift, and the shift gs[0]\mathrm{gs}[0] after an occurrence, are at least 1 and skip no valid shift. So ss increases at each window, every valid shift is tested, and only valid shifts are output, in increasing order. The loop stops once s>n−ms > n - m, after at most n−m+1n - m + 1 windows. ■\blacksquare

Back to Apostolico-Giancarlo algorithm