Algorithm Search⌘K

Proofs: Galil-Seiferas algorithm

These are the human proofs of Galil-Seiferas algorithm, at full length.

Galil-Seiferas outputs exactly the valid shifts full

This proof shows: correctness, termination.

Claim. For a text T[0…n−1]T[0 \ldots n-1], a pattern P[0…m−1]P[0 \ldots m-1] over any alphabet with equality tests, and an integer k≥3k \ge 3, GALIL-SEIFERAS(T,P)(T, P) stops and outputs exactly the shifts pp, 0≤p≤n−m0 \le p \le n - m, with T[p…p+m−1]=PT[p \ldots p+m-1] = P, in increasing order.

For m=0m = 0, line L2 outputs every shift, so let m≥1m \ge 1. Throughout, v=P[s…m−1]v = P[s \ldots m-1] for the current value of ss.

Definitions and facts. For a string ww, per(w)\mathrm{per}(w) is its smallest period. For 1≤p≤∣v∣1 \le p \le |v|, reach(p)\mathrm{reach}(p) is the length of the longest prefix of vv with period pp; so reach(p)≥p\mathrm{reach}(p) \ge p, and if reach(p)<∣v∣\mathrm{reach}(p) < |v| then v[reach(p)]≠v[reach(p)−p]v[\mathrm{reach}(p)] \ne v[\mathrm{reach}(p) - p]. A length pp is a prefix period if v[0…p−1]v[0 \ldots p-1] is primitive and reach(p)≥kp\mathrm{reach}(p) \ge kp, and good if reach(p)≥kp\mathrm{reach}(p) \ge kp or reach(p)=∣v∣\mathrm{reach}(p) = |v|. We use three standard facts.

(F1) If π=per(w)\pi = \mathrm{per}(w) then w[0…π−1]w[0 \ldots \pi-1] is primitive: if it were yry^r with r≥2r \ge 2, then ww, a prefix of y∞y^\infty, would have the smaller period ∣y∣|y|.

(F2) Fine and Wilf: if ww has periods aa and bb and ∣w∣≥a+b−gcd⁡(a,b)|w| \ge a + b - \gcd(a, b), it has period gcd⁡(a,b)\gcd(a, b).

(F3) If z=v[0…p−1]z = v[0 \ldots p-1] is primitive, a prefix ww of vv with period pp and ∣w∣≥p|w| \ge p has no period g<pg < p dividing pp; with (F2), if ww also has a period dd and ∣w∣≥p+d|w| \ge p + d, then pp divides dd. Indeed zz would have period g∣pg \mid p, g<pg < p, making it a power.

(F4) If v[0…L−1]v[0 \ldots L-1] has period dd and L≥kdL \ge kd, then π=per(v[0…L−1])≤d\pi = \mathrm{per}(v[0 \ldots L-1]) \le d is a prefix period, by (F1) and reach(π)≥L≥kπ\mathrm{reach}(\pi) \ge L \ge k\pi.

The properties of the factorization. We show that whenever FACTORIZE returns (s,p1,q1)(s, p_1, q_1): (S1) every prefix period of vv equals p1p_1; (S2) p1+q1=reach(p1)p_1 + q_1 = \mathrm{reach}(p_1); (S3) p1=per(v[0…p1+q1−1])p_1 = \mathrm{per}(v[0 \ldots p_1 + q_1 - 1]).

Write R=p1+q1R = p_1 + q_1. The invariant of lines L11 to L15 and of the loop of lines L24 to L29, at the start of lines L12 and L25, is

(G) no p<p1p < p_1 is good for vv;

and after line L12 or L25 has run, R=reach(p1)R = \mathrm{reach}(p_1), because q1q_1 was 0 or already reach(p1)−p1\mathrm{reach}(p_1) - p_1 when the loop started, and the loop stops at the end of vv or at the first mismatch.

Lemma 1 (skip). Assume (G), R=reach(p1)<kp1R = \mathrm{reach}(p_1) < k p_1 and R<∣v∣R < |v|. Then no pp with p1<p≤p1+⌊q1/k⌋p_1 < p \le p_1 + \lfloor q_1/k \rfloor is good, so (G) holds after line L15 or L28.

Proof. Suppose p=p1+δp = p_1 + \delta is good, 1≤δ≤q1/k1 \le \delta \le q_1/k. Then reach(p)≥R\mathrm{reach}(p) \ge R: either reach(p)≥kp>kp1>R\mathrm{reach}(p) \ge kp > kp_1 > R, or reach(p)=∣v∣>R\mathrm{reach}(p) = |v| > R. For 0≤i<q1−δ0 \le i < q_1 - \delta, we have i+p<Ri + p < R, so v[i]=v[i+p]v[i] = v[i + p], and i+δ+p1<Ri + \delta + p_1 < R, so v[i+p]=v[(i+δ)+p1]=v[i+δ]v[i + p] = v[(i + \delta) + p_1] = v[i + \delta]. So v[0…q1−1]v[0 \ldots q_1 - 1] has period δ\delta and length q1≥kδq_1 \ge k\delta. By (F4) it has a prefix period π≤δ≤q1/k\pi \le \delta \le q_1/k, and q1=R−p1<(k−1)p1q_1 = R - p_1 < (k-1)p_1 gives π<p1\pi < p_1; a prefix period is good, against (G). □\square

Lemma 2 (the shortest prefix period). Assume (G) and R=reach(p1)≥kp1R = \mathrm{reach}(p_1) \ge kp_1. Then p1p_1 is a prefix period and p1=per(v[0…R−1])p_1 = \mathrm{per}(v[0 \ldots R-1]).

Proof. Let π=per(v[0…R−1])≤p1\pi = \mathrm{per}(v[0 \ldots R-1]) \le p_1. By (F1) v[0…π−1]v[0 \ldots \pi-1] is primitive and reach(π)≥R≥kp1≥kπ\mathrm{reach}(\pi) \ge R \ge kp_1 \ge k\pi, so π\pi is good, and (G) gives π=p1\pi = p_1. □\square

Lemma 3 (drop). Assume (G), R=reach(p1)≥kp1R = \mathrm{reach}(p_1) \ge kp_1, and let line L26 move ss by tp1tp_1, t≥1t \ge 1, to obtain v′=v[tp1…]v' = v[tp_1 \ldots] and R′=R−tp1R' = R - tp_1, with (k−1)p1≤R′<kp1(k-1)p_1 \le R' < kp_1. Then reachv′(p1)=R′\mathrm{reach}_{v'}(p_1) = R' and (G) holds for v′v'.

Proof. By Lemma 2, z=v[0…p1−1]z = v[0 \ldots p_1 - 1] is primitive. v′[0…R′−1]=v[tp1…R−1]v'[0 \ldots R'-1] = v[tp_1 \ldots R-1] is a factor of the p1p_1-periodic prefix that starts at a multiple of p1p_1, so it equals v[0…R′−1]v[0 \ldots R'-1], and the mismatch (or end) at RR in vv is at R′R' in v′v'; so reachv′(p1)=R′\mathrm{reach}_{v'}(p_1) = R'. Suppose δ<p1\delta < p_1 is good for v′v', and let L=min⁡(reachv′(δ),R′)L = \min(\mathrm{reach}_{v'}(\delta), R'); then v′[0…L−1]v'[0 \ldots L-1] has periods δ\delta and p1p_1. If L≥δ+p1L \ge \delta + p_1, (F3) applied to v′v' (which starts with zz) says p1∣δp_1 \mid \delta, impossible for 0<δ<p10 < \delta < p_1. Otherwise L<δ+p1<2p1≤(k−1)p1≤R′L < \delta + p_1 < 2p_1 \le (k-1)p_1 \le R', using k≥3k \ge 3, so L=reachv′(δ)<R′≤∣v′∣L = \mathrm{reach}_{v'}(\delta) < R' \le |v'|, and goodness gives reachv′(δ)≥kδ\mathrm{reach}_{v'}(\delta) \ge k\delta. Since vv and v′v' agree on their first R′R' characters and reachv′(δ)<R′\mathrm{reach}_{v'}(\delta) < R', the mismatch that ends the δ\delta-periodic prefix of v′v' is also one in vv, so reachv(δ)=reachv′(δ)≥kδ\mathrm{reach}_v(\delta) = \mathrm{reach}_{v'}(\delta) \ge k\delta, and δ\delta is good for vv, against (G). □\square

Lines L11 to L15. (G) holds at the first entry, with p1=1p_1 = 1, vacuously. If line L14 returns, R=∣v∣<kp1R = |v| < kp_1: by (G) no p<p1p < p_1 is a prefix period or a period of vv; p1p_1 is not a prefix period; and p>p1p > p_1 has reach(p)≤∣v∣<kp\mathrm{reach}(p) \le |v| < kp. So vv has no prefix period and p1=per(v)p_1 = \mathrm{per}(v): (S1) to (S3) hold. If line L15 runs, Lemma 1 keeps (G). If line L16 is reached, Lemma 2 applies.

Lines L17 to L23. Here p1p_1 is a prefix period with R≥kp1R \ge kp_1, z=v[0…p1−1]z = v[0 \ldots p_1-1] is primitive and p1=per(v[0…R−1])p_1 = \mathrm{per}(v[0 \ldots R-1]) (Lemma 2). The invariant at the start of line L19 is: (H1) no prefix period pp with p1<p<p2p_1 < p < p_2; (H2) p2+q2≤∣v∣p_2 + q_2 \le |v| and v[0…q2−1]=v[p2…p2+q2−1]v[0 \ldots q_2 - 1] = v[p_2 \ldots p_2 + q_2 - 1].

Start. p2=q1=R−p1≥(k−1)p1>p1p_2 = q_1 = R - p_1 \ge (k-1)p_1 > p_1 and q2=0q_2 = 0. If p1<p<q1p_1 < p < q_1 were a prefix period, then reach(p)≥kp≥p+p1\mathrm{reach}(p) \ge kp \ge p + p_1 and R=p1+q1>p+p1R = p_1 + q_1 > p + p_1, so v[0…p+p1−1]v[0 \ldots p + p_1 - 1] has periods pp and p1p_1, and (F3) for the primitive prefix of length pp gives p∣p1p \mid p_1, impossible as p>p1p > p_1.

Exits. Line L19 keeps (H2). If line L20 exits, p2p_2 is used only as a bound in lines L24 to L29, where (G) is what matters, and (G) holds there because it held at line L12 and vv, p1p_1 have not changed since. If line L21 returns, ∣v∣=p2+q2<kp2|v| = p_2 + q_2 < kp_2, so no p≥p2p \ge p_2 is a prefix period; with (H1) and (G), every prefix period equals p1p_1, and with Lemma 2 this gives (S1) to (S3).

Line L22, q2=Rq_2 = R. The loop stopped at a mismatch v[q2]≠v[p2+q2]v[q_2] \ne v[p_2 + q_2] with p2+q2<kp2p_2 + q_2 < kp_2, so reach(p2)=p2+q2<kp2\mathrm{reach}(p_2) = p_2 + q_2 < kp_2 and p2p_2 is not a prefix period. Let p=p2+δp = p_2 + \delta, 1≤δ<p11 \le \delta < p_1, be a prefix period. Then reach(p)≥kp>p2+q2\mathrm{reach}(p) \ge kp > p_2 + q_2, so for 0≤i<R−δ0 \le i < R - \delta, v[i]=v[i+p]v[i] = v[i + p] and, by (H2), v[i+p]=v[p2+(i+δ)]=v[i+δ]v[i + p] = v[p_2 + (i + \delta)] = v[i + \delta]; so v[0…R−1]v[0 \ldots R-1] has period δ<p1\delta < p_1, against Lemma 2. So (H1) holds for p2+p1p_2 + p_1. For (H2), for i<q1i < q_1: v[p2+p1+i]=v[p1+i]=v[i]v[p_2 + p_1 + i] = v[p_1 + i] = v[i], by (H2) and the period p1p_1 of v[0…R−1]v[0 \ldots R-1].

Line L23, q2≠Rq_2 \ne R. As above p2p_2 is not a prefix period. Let p=p2+δp = p_2 + \delta, 1≤δ≤q2/k1 \le \delta \le q_2/k, be one. Then reach(p)≥kp>p2+q2\mathrm{reach}(p) \ge kp > p_2 + q_2, and for 0≤i<q2−δ0 \le i < q_2 - \delta, v[i]=v[i+p]=v[p2+i+δ]=v[i+δ]v[i] = v[i + p] = v[p_2 + i + \delta] = v[i + \delta] by (H2): v[0…q2−1]v[0 \ldots q_2-1] has period δ\delta and length q2≥kδq_2 \ge k\delta. By (F4) it has a prefix period π≤δ≤q2/k<p2\pi \le \delta \le q_2/k < p_2, which is p1p_1 by (H1) and (G). So v[0…q2−1]v[0 \ldots q_2 - 1] has period p1p_1, hence q2≤Rq_2 \le R, and so q2<Rq_2 < R and v[0…q2]v[0 \ldots q_2] has period p1p_1. Also q2≥kδ≥δ+p1q_2 \ge k\delta \ge \delta + p_1 (as δ≥π=p1\delta \ge \pi = p_1), so (F3) gives p1∣δp_1 \mid \delta. Now p≤p2+q2<reach(p)p \le p_2 + q_2 < \mathrm{reach}(p), so v[p2+q2]=v[p2+q2−p]=v[q2−δ]=v[q2]v[p_2 + q_2] = v[p_2 + q_2 - p] = v[q_2 - \delta] = v[q_2], against the mismatch. (H2) holds with q2=0q_2 = 0, and p2+⌊q2/k⌋+1≤p2+q2+1≤∣v∣p_2 + \lfloor q_2/k \rfloor + 1 \le p_2 + q_2 + 1 \le |v| since p2+q2<∣v∣p_2 + q_2 < |v|.

Lines L24 to L29. (G) holds at the first entry. After line L25, if R≥kp1R \ge kp_1, line L26 drops copies and Lemma 3 gives (G) for the new vv with reach(p1)=R′<kp1\mathrm{reach}(p_1) = R' < kp_1; this does not change s+p1+q1s + p_1 + q_1. If line L27 returns, reach(p1)=∣v∣<kp1\mathrm{reach}(p_1) = |v| < kp_1, and (S1) to (S3) follow exactly as for line L14. Otherwise Lemma 1 applies to line L28.

Lemma 4 (the search). Assume (S1) to (S3), R=p1+q1R = p_1 + q_1. At the start of each window pp of line L5, T[p+s…p+s+q−1]=v[0…q−1]T[p+s \ldots p+s+q-1] = v[0 \ldots q-1]; line L7 outputs pp exactly when pp is valid; and no shift p′p' with p<p′<pnextp < p' < p_{\mathrm{next}} is valid.

Proof. The invariant holds with q=0q = 0; line L6 keeps it and stops at q=∣v∣q = |v| or at a real mismatch T[p+s+q]≠v[q]T[p+s+q] \ne v[q] (the position is inside TT because p≤n−mp \le n - m). Line L7 outputs pp exactly when vv and uu both match, that is, when pp is valid. After line L8, for i<q−p1=q1i < q - p_1 = q_1, T[p+p1+s+i]=v[p1+i]=v[i]T[p + p_1 + s + i] = v[p_1 + i] = v[i] by the period p1p_1 of v[0…R−1]v[0 \ldots R-1]; after line L9 the invariant is empty. For the shifts: p′p' valid implies vv occurs at p′+sp' + s; let d=p′−p≥1d = p' - p \ge 1. For d≤i<qd \le i < q, T[p+s+i]=v[i]T[p+s+i] = v[i] and T[p+s+i]=v[i−d]T[p+s+i] = v[i - d], so v[0…q−1]v[0 \ldots q-1] has period dd.

  • Line L8, q=Rq = R, d<p1d < p_1: v[0…R−1]v[0 \ldots R-1] has period d<p1d < p_1, against (S3).
  • Line L9, q≠Rq \ne R, d≤q/kd \le q/k: v[0…q−1]v[0 \ldots q-1] has period dd and length q≥kdq \ge kd, so by (F4) it has a prefix period π≤d\pi \le d, and π=p1\pi = p_1 by (S1). Then v[0…q−1]v[0 \ldots q-1] has period p1p_1, so q≤Rq \le R by (S2), and q<R≤∣v∣q < R \le |v|: the scan stopped at a real mismatch, and v[0…q]v[0 \ldots q] has period p1p_1. As q≥kd≥d+p1q \ge kd \ge d + p_1, (F3) gives p1∣dp_1 \mid d. The occurrence gives T[p+s+q]=v[q−d]=v[q]T[p+s+q] = v[q - d] = v[q], against the mismatch. □\square

Termination. In lines L11 to L15 and L24 to L29, p1p_1 strictly increases at lines L15 and L28, and line L26 only runs while p1+q1≥kp1p_1 + q_1 \ge kp_1, which bounds the number of drops. These lines keep p1+q1≤∣v∣≤mp_1 + q_1 \le |v| \le m: lines L15 and L28 run only when s+p1+q1<ms + p_1 + q_1 < m, and then p1+⌊q1/k⌋+1≤p1+q1+1≤∣v∣p_1 + \lfloor q_1/k \rfloor + 1 \le p_1 + q_1 + 1 \le |v|. Lines L17 to L23 strictly increase p2p_2 at each step and keep p2≤p2+q2≤∣v∣p_2 \le p_2 + q_2 \le |v| by (H2), so they stop. The loop of lines L24 to L29 ends with p1≥p2>p1oldp_1 \ge p_2 > p_1^{\mathrm{old}}, so each return to line L12 has a larger p1p_1, and since p1≤mp_1 \le m FACTORIZE returns. In the search, each shift is at least 1 and each window does at most mm steps of line L6, so the search stops after at most n−m+1n - m + 1 windows.

Proof of the claim. FACTORIZE returns with (S1) to (S3). By Lemma 4, every window is output exactly when it is valid, the shifts skip no valid shift, and pp increases, so every valid shift is output once, in increasing order. ■\blacksquare

Back to Galil-Seiferas algorithm