Algorithm Search⌘K

Proofs: Karp-Miller-Rosenberg algorithm

These are the human proofs of Karp-Miller-Rosenberg algorithm, at full length.

The KMR naming gives the ranks of all basic factors full

This proof shows: correctness, termination, time.worst.

Notation. T=T[0…n−1]T = T[0 \ldots n-1] with n≥1n \ge 1, positions 0-based. For j≥0j \ge 0 with 2j≤n2^j \le n, the basic factors of level jj are Fj(i)=T[i…i+2j−1]F_j(i) = T[i \ldots i + 2^j - 1] for 0≤i≤n−2j0 \le i \le n - 2^j. The claim is that KMR returns arrays with

(N) NAMEj[i]NAME_j[i] is the number of distinct strings among Fj(0),…,Fj(n−2j)F_j(0), \ldots, F_j(n - 2^j) that are smaller than Fj(i)F_j(i),

for every level jj with 2j≤n2^j \le n. In particular, NAMEj[i]=NAMEj[i′]NAME_j[i] = NAME_j[i'] if and only if Fj(i)=Fj(i′)F_j(i) = F_j(i'), and NAMEj[i]<NAMEj[i′]NAME_j[i] < NAME_j[i'] if and only if Fj(i)<Fj(i′)F_j(i) < F_j(i').

Lemma 1 (doubling). For 2j+1≤n2^{j+1} \le n and 0≤i≤n−2j+10 \le i \le n - 2^{j+1}, Fj+1(i)=Fj(i) Fj(i+2j)F_{j+1}(i) = F_j(i)\,F_j(i + 2^j). Two strings of the same length 2j+12^{j+1} compare as the pairs of their halves, the first half first.

Proof. The first 2j2^j symbols of Fj+1(i)F_{j+1}(i) are Fj(i)F_j(i), and the next 2j2^j are T[i+2j…i+2j+1−1]=Fj(i+2j)T[i + 2^j \ldots i + 2^{j+1} - 1] = F_j(i + 2^j); the index i+2j≤n−2ji + 2^j \le n - 2^j is a valid start of level jj. For strings x=x1x2x = x_1 x_2 and y=y1y2y = y_1 y_2 with ∣x1∣=∣y1∣|x_1| = |y_1| and ∣x2∣=∣y2∣|x_2| = |y_2|, the first difference of xx and yy is in the first halves if x1≠y1x_1 \ne y_1, and otherwise in the second halves. □\square

Theorem 1. At each test of line L3, (N) holds for the levels 0,…,j0, \ldots, j.

Proof. By induction on jj. For j=0j = 0, line L1 gives each symbol its rank among the distinct symbols, which is (N) for single symbols. Assume (N) for level jj and 2j+1≤n2^{j+1} \le n. Line L4 forms the pairs (NAMEj[i],NAMEj[i+2j])(NAME_j[i], NAME_j[i + 2^j]). By (N) for level jj, the pairs compare as (Fj(i),Fj(i+2j))(F_j(i), F_j(i + 2^j)), so by Lemma 1 they compare as Fj+1(i)F_{j+1}(i). Line L5 sorts the positions by the pairs; the two passes of the radix sort are stable counting sorts, the second key first, so the result is sorted by the pair. Lines L6 to L8 scan the sorted positions and increase the counter rr exactly when the pair differs from the one before. The first position gets r=0r = 0, and the name of a position is the number of distinct pairs before its pair in sorted order, which is the number of distinct factors of level j+1j + 1 smaller than Fj+1(i)F_{j+1}(i). That is (N) for level j+1j + 1. □\square

Termination. The level jj increases by 1 in each round, and the loop stops when 2j+1>n2^{j+1} > n, after ⌊log⁡2n⌋\lfloor \log_2 n \rfloor rounds. For n=0n = 0 the algorithm returns at once.

Corollary (comparison of factors). For 1≤ℓ≤n1 \le \ell \le n and k=⌊log⁡2ℓ⌋k = \lfloor \log_2 \ell \rfloor, the factor T[p…p+ℓ−1]T[p \ldots p + \ell - 1] is smaller than, equal to or larger than T[q…q+ℓ−1]T[q \ldots q + \ell - 1] as the pair (NAMEk[p],NAMEk[p+ℓ−2k])(NAME_k[p], NAME_k[p + \ell - 2^k]) compares with (NAMEk[q],NAMEk[q+ℓ−2k])(NAME_k[q], NAME_k[q + \ell - 2^k]).

Proof. Since 2k≤ℓ<2k+12^k \le \ell < 2^{k+1}, the two windows of length 2k2^k at offsets 0 and ℓ−2k\ell - 2^k cover the factor, and they overlap or touch. If the first windows differ, the first difference of the two factors is inside them, and (N) gives the order. If the first windows are equal, the two factors agree on offsets 00 to 2k−12^k - 1, which include the overlap ℓ−2k\ell - 2^k to 2k−12^k - 1. So their first difference, if any, is at an offset of at least 2k2^k, inside the second windows, and the second windows compare as the factors do. □\square

Theorem 2 (time). KMR takes O(nlog⁡n)O(n \log n) time and O(nlog⁡n)O(n \log n) words of space for all levels, after the symbols are mapped to their ranks.

Proof. Level j+1j + 1 has n−2j+1+1≤nn - 2^{j+1} + 1 \le n positions. Line L4 and lines L6 to L8 take O(n)O(n) time, and line L5 is two counting sorts with nn buckets, since names are below nn, so O(n)O(n) time. There are ⌊log⁡2n⌋\lfloor \log_2 n \rfloor rounds, and each level stores at most nn names. ■\blacksquare

Back to Karp-Miller-Rosenberg algorithm