Algorithm Search⌘K

Proofs: Booth's algorithm

These are the human proofs of Booth's algorithm, at full length.

LEAST-ROTATION returns the least index of a least rotation full

This proof shows: correctness, termination.

Notation. s=s[0..n−1]s = s[0..n-1] with n≥1n \ge 1 is a word over a totally ordered alphabet, with 0-based indices. Let t=sst = ss, and let t′t' be the infinite word sss⋯sss\cdots, so t′[q]=s[q mod n]t'[q] = s[q \bmod n] and t[q]=t′[q]t[q] = t'[q] for q<2nq < 2n. For q≥0q \ge 0 let R(q)=t′[q..q+n−1]R(q) = t'[q..q+n-1]. Then R(q)=R(q mod n)R(q) = R(q \bmod n), and R(0),…,R(n−1)R(0), \ldots, R(n-1) are the rotations of ss. Words are compared in lexicographic order. For a nonempty word yy and 0≤r<∣y∣0 \le r < |y|, Fy(r)F_y(r) is the length of the longest border of y[0..r]y[0..r], minus one. A border of yy is always proper here: a word that is both a proper prefix and a proper suffix of yy, possibly empty.

Lemma 1 (first difference). Let q,k,e≥0q, k, e \ge 0 with t′[q..q+e−1]=t′[k..k+e−1]t'[q..q+e-1] = t'[k..k+e-1] and t′[q+e]≠t′[k+e]t'[q+e] \ne t'[k+e]. Then e<ne < n; and R(q)<R(k)R(q) < R(k) if t′[q+e]<t′[k+e]t'[q+e] < t'[k+e], while R(q)>R(k)R(q) > R(k) if t′[q+e]>t′[k+e]t'[q+e] > t'[k+e].

Proof. If e≥ne \ge n, then R(q)=R(k)R(q) = R(k), that is, s[(q+d) mod n]=s[(k+d) mod n]s[(q+d) \bmod n] = s[(k+d) \bmod n] for 0≤d<n0 \le d < n. Both sides depend only on d mod nd \bmod n, so the equality holds for every d≥0d \ge 0, in particular for d=ed = e, a contradiction. So e<ne < n, and the words R(q)R(q) and R(k)R(k) of length nn agree before offset ee and differ at it. □\square

Lemma 2 (borders of a border). Let bb be a border of xx. A word shorter than bb is a border of xx if and only if it is a border of bb.

Proof. A word shorter than bb is a prefix of xx if and only if it is a prefix of bb, because bb is a prefix of xx; the same holds for suffixes, because bb is a suffix of xx. □\square

Call an index qq decided for the candidate kk if R(q)≥R(k)R(q) \ge R(k).

Outer invariant. At the start of the iteration for jj, where 1≤j≤2n1 \le j \le 2n and j=2nj = 2n means after the loop, let x=t[k..j−1]x = t[k..j-1]. Then:

  • (I1) k<jk < j, and f[r]=Fx(r)f[r] = F_x(r) for 0≤r<∣x∣0 \le r < |x|.
  • (I2) Each qq with 0≤q<j0 \le q < j and q≠kq \ne k is decided, or has q>kq > k with t[q..j−1]t[q..j-1] a nonempty border of xx.

Initialization. At j=1j = 1, k=0k = 0, x=t[0]x = t[0] and f[0]=−1=Fx(0)f[0] = -1 = F_x(0). The only index below 1 is kk itself.

Inner invariant. Fix an iteration j≤2n−1j \le 2n - 1 and let c=t[j]c = t[j]. At each test of line L4, with the current values of kk and ii and with x=t[k..j−1]x = t[k..j-1]:

  • (J1) k<jk < j, f[r]=Fx(r)f[r] = F_x(r) for 0≤r<∣x∣0 \le r < |x|, and i+1i + 1 is the length of a border of xx.
  • (J2) Each q<jq < j with q≠kq \ne k is decided, or has q>kq > k with t[q..j−1]t[q..j-1] a nonempty border of xx of length at most i+1i + 1.
  • (J3) Each nonempty border uu of xx longer than i+1i + 1 has x[∣u∣]≠cx[|u|] \ne c.

First test. Line L3 sets i=f[∣x∣−1]=Fx(∣x∣−1)i = f[|x| - 1] = F_x(|x| - 1), so i+1i + 1 is the length of the longest border of xx. Then (J1) and (J2) follow from (I1) and (I2), and (J3) is empty.

One pass of lines L5 and L6. The test passed, so i≥0i \ge 0 and c≠x[i+1]c \ne x[i+1], where x[i+1]=t[k+i+1]x[i+1] = t[k+i+1] exists because i+1<∣x∣i + 1 < |x|. Let b=x[0..i]b = x[0..i], a border of xx, and p=j−i−1>kp = j - i - 1 > k. Then t[p..j−1]=b=t[k..k+i]t[p..j-1] = b = t[k..k+i], and t[p..j]t[p..j] and t[k..k+i+1]t[k..k+i+1] first differ at offset i+1i + 1, where cc meets x[i+1]x[i+1].

  • If c>x[i+1]c > x[i+1], Lemma 1 gives R(p)>R(k)R(p) > R(k), so pp becomes decided. Line L6 sets ii to f[i]=Fx(i)f[i] = F_x(i), so i+1i + 1 becomes the length of the longest border of bb. The undecided indices of (J2) other than pp have borders of xx shorter than bb, which by Lemma 2 are borders of bb, so their length is at most the new i+1i + 1. By Lemma 2, the borders of xx longer than the new i+1i + 1 are those longer than the old i+1i + 1, and bb; all of them have x[∣u∣]≠cx[|u|] \ne c. So (J1) to (J3) hold.
  • If c<x[i+1]c < x[i+1], Lemma 1 gives R(p)<R(k)R(p) < R(k), and line L5 sets kk to pp. The new word xx is bb, a prefix of the old xx, so f[r]=Fb(r)f[r] = F_b(r) for r≤ir \le i. Each index decided for the old candidate is decided for pp, since R(q)≥R(kold)>R(p)R(q) \ge R(k_{\text{old}}) > R(p), and so is koldk_{\text{old}} itself. Each other undecided index q≠pq \ne p has a border of the old xx shorter than bb, so q>pq > p, and by Lemma 2 its border is a border of bb, the new xx. Line L6 sets ii to f[i]f[i], the length of the longest border of bb, minus one. So (J1) and (J2) hold, and (J3) is empty, because no border of bb is longer than its longest border.

Each pass decreases ii, and i≥−1i \ge -1, so the inner loop stops.

Maintenance of the outer invariant. At the exit from the inner loop, (J1) to (J3) hold, and either i≥0i \ge 0 with c=x[i+1]c = x[i+1], or i=−1i = -1.

Case A: i≥0i \ge 0 and c=x[i+1]c = x[i+1]. Line L7 fails and line L10 sets f[∣x∣]=i+1f[|x|] = i + 1. Let y=xc=t[k..j]y = xc = t[k..j], the word xx of the iteration j+1j + 1.

  • The table. A nonempty border of yy has the form ucuc, where uu is a border of xx with x[∣u∣]=cx[|u|] = c. By (J3) the longest such uu is x[0..i]x[0..i], so Fy(∣x∣)=i+1F_y(|x|) = i + 1. The entries below ∣x∣|x| are unchanged and stay correct, since y[0..r]=x[0..r]y[0..r] = x[0..r].
  • The key claim. Let uu be a border of xx with ∣u∣<i+1|u| < i + 1 and x[∣u∣]≠cx[|u|] \ne c. Then c>x[∣u∣]c > x[|u|]. Indeed, uu is a border of b=x[0..i]b = x[0..i] by Lemma 2, so uu ends bb, and bc=x[0..i+1]bc = x[0..i+1] is a prefix of xx. So ucuc occurs in tt at the index q′=k+i+1−∣u∣q' = k + i + 1 - |u|, where k<q′<jk < q' < j and q′+∣u∣=k+i+1≤j−1q' + |u| = k + i + 1 \le j - 1. By (J2), q′q' is decided, or t[q′..j−1]t[q'..j-1] is a border of xx. In the second case t[q′..j−1]t[q'..j-1] is a prefix of xx that covers the index q′+∣u∣q' + |u|, so x[∣u∣]=t[q′+∣u∣]=cx[|u|] = t[q' + |u|] = c, which is excluded. In the first case R(q′)≥R(k)R(q') \ge R(k); but t[q′..q′+∣u∣−1]=u=t[k..k+∣u∣−1]t[q'..q'+|u|-1] = u = t[k..k+|u|-1], and at offset ∣u∣|u| the letters are cc and x[∣u∣]x[|u|], so c<x[∣u∣]c < x[|u|] would give R(q′)<R(k)R(q') < R(k) by Lemma 1. Hence c>x[∣u∣]c > x[|u|].
  • The indices. A decided index stays decided. An undecided q<jq < j has a border u=t[q..j−1]u = t[q..j-1] of xx of length at most i+1i + 1. If x[∣u∣]=cx[|u|] = c, then t[q..j]=uc=x[0..∣u∣]t[q..j] = uc = x[0..|u|] is a border of yy. If x[∣u∣]≠cx[|u|] \ne c, then ∣u∣<i+1|u| < i + 1 (for u=bu = b the letter is cc), so c>x[∣u∣]c > x[|u|] by the key claim, and Lemma 1 at offset ∣u∣|u| gives R(q)>R(k)R(q) > R(k). The new index q=jq = j is the case u=εu = \varepsilon: if x[0]=cx[0] = c, then t[j..j]=ct[j..j] = c is a border of yy, and otherwise the key claim with u=εu = \varepsilon gives c>x[0]c > x[0], so R(j)>R(k)R(j) > R(k).

So (I1) and (I2) hold at j+1j + 1.

Case B: i=−1i = -1. By (J2) every q<jq < j other than kk is decided, and by (J3) every nonempty border uu of xx has x[∣u∣]≠cx[|u|] \ne c. So the only possible nonempty border of y=xcy = xc is cc itself, which is a border exactly when c=x[0]=t[k]c = x[0] = t[k]. The new index jj meets kk at offset 0.

  • If c=t[k]c = t[k], line L10 sets f[∣x∣]=0=Fy(∣x∣)f[|x|] = 0 = F_y(|x|), and jj is undecided with the border t[j..j]=ct[j..j] = c of yy.
  • If c>t[k]c > t[k], line L9 sets f[∣x∣]=−1=Fy(∣x∣)f[|x|] = -1 = F_y(|x|), and R(j)>R(k)R(j) > R(k) by Lemma 1.
  • If c<t[k]c < t[k], then R(j)<R(k)R(j) < R(k) by Lemma 1, and line L8 sets k←jk \leftarrow j. Each q<jq < j has R(q)≥R(kold)>R(j)R(q) \ge R(k_{\text{old}}) > R(j), so it is decided for jj. The new xx is t[j..j]t[j..j], and line L9 sets f[0]=−1f[0] = -1, which is correct.

In all cases (I1) and (I2) hold at j+1j + 1. The outer loop runs 2n−12n - 1 times and each inner loop stops, so the algorithm terminates.

The output is a least rotation. At the end, j=2nj = 2n and x=t[k..2n−1]x = t[k..2n-1]. Let 0≤q<n0 \le q < n with q≠kq \ne k. By (I2), R(q)≥R(k)R(q) \ge R(k), or q>kq > k and t[q..2n−1]t[q..2n-1] is a border of xx. In the second case this border has length 2n−q>n2n - q > n and is a prefix of xx, so its first nn letters, R(q)R(q), are the first nn letters of xx, which are R(k)R(k). So R(k)≤R(q)R(k) \le R(q) for every q<nq < n, and R(k)=R(k mod n)R(k) = R(k \bmod n) is a least rotation.

The output is the least such index, and k<nk < n. Let mm be the least index in [0,2n)[0, 2n) with R(m)R(m) minimal; since R(m+n)=R(m)R(m + n) = R(m), m<nm < n. Each change of kk, at line L5 or L8, is to an index with a strictly smaller rotation, by the cases above. So once k=mk = m, it never changes. Suppose the final value kfk_f differs from mm. Then R(kf)R(k_f) is minimal, as shown, so kf>m≥0k_f > m \ge 0 by the choice of mm, and kk was set to kfk_f at some step of some iteration j0j_0, from a candidate kck_c with R(kc)>R(kf)=R(m)R(k_c) > R(k_f) = R(m). Then kc≠mk_c \ne m and m<kf≤j0m < k_f \le j_0. At the test of line L4 just before this step, (J2) holds, and mm is not decided for kck_c, since R(m)<R(kc)R(m) < R(k_c). So t[m..j0−1]t[m..j_0-1] is a nonempty border of xx of length at most i+1i + 1. If the step is line L5, then kf=j0−i−1k_f = j_0 - i - 1 and j0−m>j0−kf=i+1j_0 - m > j_0 - k_f = i + 1, a contradiction. If the step is line L8, then i=−1i = -1, and no nonempty border has length at most 0, a contradiction. So kf=mk_f = m: the algorithm returns the least index of a least rotation, and it lies in [0,n)[0, n). ■\blacksquare

Back to Booth's algorithm