Algorithm Search⌘K

Proofs: Bitap algorithm

These are the human proofs of Bitap algorithm, at full length.

The bitap algorithm reports exactly the windows with at most k mismatches full

This proof shows: correctness.

Indices are 0-based, ∣P∣=m≥1|P| = m \ge 1, ∣T∣=n|T| = n, and B=⌈log⁡2(k+1)⌉+1B = \lceil \log_2(k+1) \rceil + 1, so 2B−1≥k+12^{B-1} \ge k + 1. For a vector VV of mBmB bits, ViV_i is the value of field ii, bits iBiB to iB+B−1iB + B - 1. Each field of HH is 2B−12^{B-1}. Each field of M[c]M[c] is [P[i]≠c][P[i] \ne c], which is 0 or 1. For 0≤i≤j0 \le i \le j, mm(i,j)=∣{q≤i:P[q]≠T[j−i+q]}∣\mathrm{mm}(i, j) = |\{ q \le i : P[q] \ne T[j - i + q] \}|.

Lemma 1. mm(0,j)=[P[0]≠T[j]]\mathrm{mm}(0, j) = [P[0] \ne T[j]], and mm(i,j)=mm(i−1,j−1)+[P[i]≠T[j]]\mathrm{mm}(i, j) = \mathrm{mm}(i-1, j-1) + [P[i] \ne T[j]] for 1≤i≤j1 \le i \le j.

Proof. The first claim is the definition with i=0i = 0. For i≥1i \ge 1, split the positions q≤iq \le i into q≤i−1q \le i - 1 and q=iq = i. The positions q≤i−1q \le i - 1 compare P[q]P[q] with T[(j−1)−(i−1)+q]T[(j-1) - (i-1) + q], and they count mm(i−1,j−1)\mathrm{mm}(i-1, j-1). The position q=iq = i compares P[i]P[i] with T[j]T[j]. □\square

Invariant. After the loop body for index jj, for each ii with 0≤i≤m−10 \le i \le m - 1:

  1. Si<2B−1S_i < 2^{B-1}, and Oi∈{0,2B−1}O_i \in \{0, 2^{B-1}\};
  2. if i≤ji \le j and Oi=0O_i = 0, then Si=mm(i,j)S_i = \mathrm{mm}(i, j);
  3. if i≤ji \le j and Oi=2B−1O_i = 2^{B-1}, then mm(i,j)≥2B−1\mathrm{mm}(i, j) \ge 2^{B-1}.

Before the loop, S=O=0S = O = 0, so part 1 holds, and parts 2 and 3 are empty. Call this the state after step −1-1.

Step. Assume the invariant after step j−1j - 1, and let S′S', O′O' be the vectors after step jj.

No carry: in line L5, the shift moves each field i−1i - 1 to field ii for 1≤i≤m−11 \le i \le m - 1, puts 0 in field 0, and drops field m−1m - 1 by the reduction mod 2mB2^{mB}. The shifted field is below 2B−12^{B-1} by part 1, and M[T[j]]i≤1M[T[j]]_i \le 1, so the sum of the two is at most 2B−1≤2B−12^{B-1} \le 2^B - 1. So the addition creates no carry between fields, and after line L5 the field ii is ui=Si−1+[P[i]≠T[j]]u_i = S_{i-1} + [P[i] \ne T[j]] for i≥1i \ge 1, and u0=[P[0]≠T[j]]u_0 = [P[0] \ne T[j]]. Each uiu_i is at most 2B−12^{B-1}, so its top bit is set exactly when ui=2B−1u_i = 2^{B-1}.

Line L6 gives Oi′=Oi−1∨(top bit of ui)O'_i = O_{i-1} \vee (\text{top bit of } u_i) for i≥1i \ge 1 and $O'_0 = $ the top bit of u0u_0, where both sides are 0 or 2B−12^{B-1} and the shift again moves whole fields. Line L7 gives Si′=uiS'_i = u_i when ui<2B−1u_i < 2^{B-1} and Si′=0S'_i = 0 when ui=2B−1u_i = 2^{B-1}. So part 1 holds after step jj.

Fix i≤ji \le j. Case i=0i = 0: u0=mm(0,j)≤1u_0 = \mathrm{mm}(0, j) \le 1 by Lemma 1. If O0′=0O'_0 = 0, then S0′=u0=mm(0,j)S'_0 = u_0 = \mathrm{mm}(0, j). If O0′=2B−1O'_0 = 2^{B-1}, then u0=2B−1u_0 = 2^{B-1}, which needs B=1B = 1, and then mm(0,j)=1=2B−1\mathrm{mm}(0, j) = 1 = 2^{B-1}. Case i≥1i \ge 1: then i−1≤j−1i - 1 \le j - 1, so the invariant applies to field i−1i - 1 after step j−1j - 1.

  • If Oi−1=2B−1O_{i-1} = 2^{B-1}, then mm(i−1,j−1)≥2B−1\mathrm{mm}(i-1, j-1) \ge 2^{B-1} by part 3, so mm(i,j)≥2B−1\mathrm{mm}(i, j) \ge 2^{B-1} by Lemma 1. Also Oi′=2B−1O'_i = 2^{B-1}. Part 3 holds, and part 2 is empty.
  • If Oi−1=0O_{i-1} = 0, then Si−1=mm(i−1,j−1)S_{i-1} = \mathrm{mm}(i-1, j-1) by part 2, so ui=mm(i,j)u_i = \mathrm{mm}(i, j) by Lemma 1. If ui<2B−1u_i < 2^{B-1}, then Oi′=0O'_i = 0 and Si′=ui=mm(i,j)S'_i = u_i = \mathrm{mm}(i, j), which is part 2. If ui=2B−1u_i = 2^{B-1}, then Oi′=2B−1O'_i = 2^{B-1} and mm(i,j)=2B−1\mathrm{mm}(i, j) = 2^{B-1}, which is part 3.

So the invariant holds after each step. □\square

Theorem. For m≥1m \ge 1, line L8 reports i=j−m+1i = j - m + 1 exactly when 0≤i≤n−m0 \le i \le n - m and PP and T[i…i+m)T[i \ldots i + m) differ in at most kk positions.

Proof. Line L8 runs for j=m−1,…,n−1j = m - 1, \ldots, n - 1, which gives exactly the starts i=j−m+1i = j - m + 1 in 0,…,n−m0, \ldots, n - m. For such jj, the field index m−1m - 1 is at most jj, and mm(m−1,j)\mathrm{mm}(m - 1, j) is the number of positions where PP and T[j−m+1…j]T[j - m + 1 \ldots j] differ. By part 1 of the invariant, Sm−1<2B−1S_{m-1} < 2^{B-1} and Om−1O_{m-1} is 0 or 2B−12^{B-1}, so field m−1m - 1 of S∨OS \vee O is Sm−1+Om−1S_{m-1} + O_{m-1}. If Om−1=0O_{m-1} = 0, this value is mm(m−1,j)\mathrm{mm}(m-1, j) by part 2, and the test is the condition of the theorem. If Om−1=2B−1O_{m-1} = 2^{B-1}, the value is at least 2B−1≥k+12^{B-1} \ge k + 1, so the test fails, and mm(m−1,j)≥2B−1>k\mathrm{mm}(m-1, j) \ge 2^{B-1} > k by part 3, so the window is not a match either. ■\blacksquare

Back to Bitap algorithm