Algorithm Search⌘K

Proofs: r-index

These are the human proofs of r-index, at full length.

The r-index counts and locates correctly from O(r) samples full

This proof shows: correctness.

Let t=S$t = S\$ with ∣t∣=N=n+1|t| = N = n + 1, where $\$ is the unique smallest symbol and t[N−1]=$t[N-1] = \$. Let SASA be its suffix array, ISAISA the inverse, and BWT[i]=t[(SA[i]−1) mod N]BWT[i] = t[(SA[i] - 1) \bmod N]. Let C[c]C[c] be the number of symbols of tt smaller than cc and rankc(i)rank_c(i) the number of cc in BWT[0…i−1]BWT[0 \ldots i-1]. Define LF(i)=C[c]+rankc(i)LF(i) = C[c] + rank_c(i) for c=BWT[i]c = BWT[i]. A row ii is a run start if i=0i = 0 or BWT[i]≠BWT[i−1]BWT[i] \ne BWT[i-1], and a run end if i=N−1i = N - 1 or BWT[i]≠BWT[i+1]BWT[i] \ne BWT[i+1].

Lemma 1 (LF). SA[LF(i)]=(SA[i]−1) mod NSA[LF(i)] = (SA[i] - 1) \bmod N. Moreover, if XX is a string and [sp,ep)[sp, ep) is the set of rows whose suffixes start with XX, then the rows whose suffixes start with cXcX are [C[c]+rankc(sp), C[c]+rankc(ep))[C[c] + rank_c(sp),\ C[c] + rank_c(ep)), and for each row i∈[sp,ep)i \in [sp, ep) with BWT[i]=cBWT[i] = c, LF(i)LF(i) is in this range, in the same order.

Proof. Let j=SA[i]j = SA[i] and c=BWT[i]=t[j−1]c = BWT[i] = t[j-1] (cyclically). The suffixes that start with cc are the rows C[c]C[c] to C[c+1]−1C[c + 1] - 1, sorted by what follows cc. The suffix tj−1=c tjt_{j-1} = c\,t_j is preceded, among those starting with cc, exactly by the c tj′c\,t_{j'} with tj′<tjt_{j'} < t_j, that is with BWTBWT value cc in a row before ii; there are rankc(i)rank_c(i) of them. So the row of tj−1t_{j-1} is C[c]+rankc(i)C[c] + rank_c(i). (For c=$c = \$, j=0j = 0 and tN−1=$t_{N-1} = \$ is row 0 =C[$]+0= C[\$] + 0.) The suffixes starting with cXcX are the c tjc\,t_j with tjt_j starting with XX, that is with rows in [sp,ep)[sp, ep) and BWT=cBWT = c; these are mapped by LFLF in order onto consecutive rows starting at C[c]+rankc(sp)C[c] + rank_c(sp), and their number is rankc(ep)−rankc(sp)rank_c(ep) - rank_c(sp). □\square

Lemma 2 (run-length rank). Let the runs of cc be [s1,e1],…,[sq,eq][s_1, e_1], \ldots, [s_q, e_q] in order and bjb_j the number of cc before sjs_j. For 0≤i≤N0 \le i \le N, let jj be the largest index with sj≤i−1s_j \le i - 1 (none if i−1<s1i - 1 < s_1). Then rankc(i)=0rank_c(i) = 0 if there is no such jj, and otherwise rankc(i)=bj+min⁡(i,ej+1)−sjrank_c(i) = b_j + \min(i, e_j + 1) - s_j.

Proof. Every cc before row ii lies in a run of cc that starts before ii, so in runs 1,…,j1, \ldots, j. Runs 11 to j−1j - 1 end before sjs_j and contribute bjb_j in total. Run jj contributes the rows from sjs_j to min⁡(ej,i−1)\min(e_j, i - 1). □\square

Similarly, BWT[i]BWT[i] is the head of the last run with start at most ii. So the run tables compute CC, rankrank and BWTBWT exactly.

Lemma 3 (toehold). Suppose [sp,ep)[sp, ep) is nonempty, s=SA[ep−1]s = SA[ep - 1], and some row in [sp,ep)[sp, ep) has BWT=cBWT = c. Let qq be the last such row and [sp′,ep′)[sp', ep') the new range from Lemma 1. Then SA[ep′−1]=SA[q]−1SA[ep' - 1] = SA[q] - 1, and SA[q]=sSA[q] = s if q=ep−1q = ep - 1, while otherwise qq is a run end of a run of cc, namely the end of the last run of cc that starts before epep.

Proof. By Lemma 1, LFLF maps the rows of [sp,ep)[sp, ep) with BWT=cBWT = c in order onto [sp′,ep′)[sp', ep'), so the last one, qq, goes to ep′−1ep' - 1, and SA[ep′−1]=SA[q]−1SA[ep' - 1] = SA[q] - 1 (not cyclic, since c≠$c \ne \$ gives SA[q]≥1SA[q] \ge 1). If q<ep−1q < ep - 1, then BWT[q+1]≠cBWT[q + 1] \ne c because qq is the last cc in the range and q+1≤ep−1q + 1 \le ep - 1; so qq is a run end. The run of qq starts at or before q<epq < ep, and no later run of cc starts before epep, since its rows would be cc rows in (q,ep)(q, ep). □\square

Search. By induction on the number of symbols read, SEARCH keeps [sp,ep)[sp, ep) as the rows of the current suffix of PP, and s=SA[ep−1]s = SA[ep - 1] when the range is not empty. At the start, the range is all rows and s=SA[N−1]s = SA[N - 1], which is the sample at the end of the last run. In a step, line L4 or L5 finds SA[q]SA[q] by Lemma 3; if no row of the range has BWT=cBWT = c, then the last run of cc that starts before epep ends before spsp, or does not exist, and the new range is empty by Lemma 1, so returning empty is correct. Lines L6 to L8 compute the new range and the new toehold. So count(P) =ep−sp= ep - sp is the number of suffixes of tt that start with PP, which is the number of occurrences of PP in SS, since PP contains no $\$.

Lemma 4 (ϕ\phi). Let ϕ(j)=SA[ISA[j]−1]\phi(j) = SA[ISA[j] - 1] for each jj with ISA[j]≥1ISA[j] \ge 1. If j≥1j \ge 1, ISA[j]≥1ISA[j] \ge 1, and ISA[j]ISA[j] is not a run start, then ϕ(j−1)=ϕ(j)−1\phi(j - 1) = \phi(j) - 1.

Proof. Let i=ISA[j]≥1i = ISA[j] \ge 1. As ii is not a run start, BWT[i−1]=BWT[i]=cBWT[i - 1] = BWT[i] = c, and c≠$c \ne \$ because $\$ occurs once in the BWT. By Lemma 1, LF(i−1)=LF(i)−1LF(i - 1) = LF(i) - 1. Then SA[LF(i)]=j−1SA[LF(i)] = j - 1, so ISA[j−1]=LF(i)≥1ISA[j - 1] = LF(i) \ge 1, and ϕ(j−1)=SA[LF(i)−1]=SA[LF(i−1)]=SA[i−1]−1=ϕ(j)−1\phi(j - 1) = SA[LF(i) - 1] = SA[LF(i - 1)] = SA[i - 1] - 1 = \phi(j) - 1. □\square

Lemma 5 (ϕ\phi from samples). Let K={SA[p]−1:p a run start,SA[p]≥1}K = \{SA[p] - 1 : p \text{ a run start}, SA[p] \ge 1\}, with the value ϕ(y)\phi(y) stored for each y∈Ky \in K. For each xx with 0≤x0 \le x and ISA[x]≥1ISA[x] \ge 1, the set KK has an element y≥xy \ge x, and for the smallest one, ϕ(x)=ϕ(y)−(y−x)\phi(x) = \phi(y) - (y - x).

Proof. Row 0 is a run start, with SA[0]=N−1SA[0] = N - 1, so N−2∈KN - 2 \in K when N≥2N \ge 2; every xx with ISA[x]≥1ISA[x] \ge 1 has x≤N−2x \le N - 2, since ISA[N−1]=0ISA[N - 1] = 0. So yy exists. For each zz with x<z≤yx < z \le y, the row ISA[z]ISA[z] is not a run start: if it were, z−1∈Kz - 1 \in K (note SA[ISA[z]]=z≥1SA[ISA[z]] = z \ge 1) with x≤z−1<yx \le z - 1 < y, against the choice of yy. Also ISA[z]≥1ISA[z] \ge 1 since z≤N−2z \le N - 2. By Lemma 4 applied to z=y,y−1,…,x+1z = y, y - 1, \ldots, x + 1, ϕ(z−1)=ϕ(z)−1\phi(z - 1) = \phi(z) - 1, and so ϕ(x)=ϕ(y)−(y−x)\phi(x) = \phi(y) - (y - x). □\square

Locate. After SEARCH, s=SA[ep−1]s = SA[ep - 1]. Each application of ϕ\phi in line L9 maps SA[i]SA[i] to SA[i−1]SA[i - 1] for a row i≥sp+1≥1i \ge sp + 1 \ge 1, which is defined, and Lemma 5 computes it from the samples. So line L9 reports SA[ep−1],SA[ep−2],…,SA[sp]SA[ep - 1], SA[ep - 2], \ldots, SA[sp], the positions of all occurrences, each once. ■\blacksquare

Back to r-index