Algorithm Search⌘K

Proofs: Bit-parallel LCS algorithm

These are the human proofs of Bit-parallel LCS algorithm, at full length.

The bit-parallel update computes the steps of each LCS column full

This proof shows: correctness.

We use the pseudocode of the page. Let c[i,j]=lcs(Xi,Yj)c[i, j] = \mathrm{lcs}(X_i, Y_j) for 0≤i≤m0 \le i \le m, 0≤j≤n0 \le j \le n. Bit i−1i - 1 of a word is called row ii. For a column jj let δj(i)=c[i,j]−c[i−1,j]\delta_j(i) = c[i, j] - c[i - 1, j] for 1≤i≤m1 \le i \le m, and let EjE_j be the mm-bit word whose row ii is 1−δj(i)1 - \delta_j(i). A row with δj(i)=1\delta_j(i) = 1 is a step of column jj.

Lemma 1 (unit differences). For all i,j≥1i, j \ge 1: c[i,j]−c[i−1,j]∈{0,1}c[i, j] - c[i - 1, j] \in \{0, 1\} and c[i,j]−c[i,j−1]∈{0,1}c[i, j] - c[i, j - 1] \in \{0, 1\}. So EjE_j is well defined.

Proof. Adding one item to one of the two sequences cannot lower the LCS length, and it raises it by at most 1, since deleting that item from a common subsequence of the longer prefixes leaves a common subsequence that is shorter by at most 1. □\square

Lemma 2 (block rule). Fix j≥1j \ge 1, write ai=c[i,j−1]a_i = c[i, j - 1], bi=c[i,j]b_i = c[i, j] and y=yjy = y_j. Let 1≤s≤e≤m1 \le s \le e \le m be rows with bs−1=as−1b_{s-1} = a_{s-1}, no step of column j−1j - 1 at rows s,…,e−1s, \ldots, e - 1, and a step at row ee. Let ff be the first row in [s,e][s, e] with xf=yx_f = y, if there is one. Then in rows s,…,es, \ldots, e, column jj has exactly one step, at row ff if ff exists and at row ee otherwise, and be=aeb_e = a_e.

The same holds for a final run: if column j−1j - 1 has no step at rows s,…,ms, \ldots, m and bs−1=as−1b_{s-1} = a_{s-1}, then column jj has exactly one step in these rows, at the first row ff with xf=yx_f = y, if there is one, and no step otherwise.

Proof. Let A=as−1A = a_{s-1}. By the assumptions, ai=Aa_i = A for s−1≤i≤e−1s - 1 \le i \le e - 1 and ae=A+1a_e = A + 1. The LCS recurrence in the form of the LCS table is bi=ai−1+1b_i = a_{i-1} + 1 if xi=yx_i = y, and bi=max⁡(ai,bi−1)b_i = \max(a_i, b_{i-1}) otherwise. By Lemma 1, ai≤bi≤ai+1a_i \le b_i \le a_i + 1.

Rows before ff (or all rows s,…,e−1s, \ldots, e - 1 if ff does not exist or f=ef = e): they are not matches, so bi=max⁡(ai,bi−1)=max⁡(A,bi−1)b_i = \max(a_i, b_{i-1}) = \max(A, b_{i-1}), and from bs−1=Ab_{s-1} = A we get bi=Ab_i = A. No step.

If ff exists and f≤e−1f \le e - 1: bf=af−1+1=A+1b_f = a_{f-1} + 1 = A + 1, a step. For f<i≤e−1f < i \le e - 1, A+1=bf≤bi≤ai+1=A+1A + 1 = b_f \le b_i \le a_i + 1 = A + 1, so no step. At ee: be≥be−1=A+1b_e \ge b_{e-1} = A + 1; if xe=yx_e = y, be=ae−1+1=A+1b_e = a_{e-1} + 1 = A + 1; otherwise be=max⁡(ae,be−1)=A+1b_e = \max(a_e, b_{e-1}) = A + 1. So no step at ee, and be=A+1=aeb_e = A + 1 = a_e.

If f=ef = e: be=ae−1+1=A+1b_e = a_{e-1} + 1 = A + 1, a step at ee, and be=aeb_e = a_e.

If ff does not exist: be=max⁡(ae,be−1)=max⁡(A+1,A)=A+1b_e = \max(a_e, b_{e-1}) = \max(A + 1, A) = A + 1, a step at ee, and be=aeb_e = a_e.

For a final run, the same argument without the row ee gives the claim. □\square

Lemma 3 (blocks cover the column). Let column j−1j - 1 have steps at rows e1<⋯<ete_1 < \cdots < e_t. Split the rows into the blocks [1,e1],[e1+1,e2],…,[et−1+1,et][1, e_1], [e_1 + 1, e_2], \ldots, [e_{t-1} + 1, e_t] and the final run [et+1,m][e_t + 1, m] (empty if et=me_t = m). Then Lemma 2 applies to each of them, and so it describes all steps of column jj.

Proof. The first block starts at s=1s = 1 with b0=a0=0b_0 = a_0 = 0. Each block ends with be=aeb_e = a_e by Lemma 2, which is the condition bs−1=as−1b_{s-1} = a_{s-1} for the next block or the final run. □\square

Lemma 4 (the word operations). Let V=Ej−1V = E_{j-1}, M=M[yj]M = M[y_j], U=V∧MU = V \wedge M, and W=((V+U)∨(V∧¬M)) mod 2mW = ((V + U) \vee (V \wedge \neg M)) \bmod 2^m. Then W=EjW = E_j.

Proof. In VV, a block [s,e][s, e] of Lemma 3 is a run of 1 bits at rows s,…,e−1s, \ldots, e - 1 and a 0 bit at row ee; the final run is 1 bits at rows s,…,ms, \ldots, m. Since U⊆VU \subseteq V, UU has no bit at any row ee.

No carry between blocks. Consider the part of V+UV + U formed by the bits of one block [s,e][s, e]. Its value in VV is 2e−1−2s−12^{e-1} - 2^{s-1} (bits s−1s - 1 to e−2e - 2), and in UU it is a subset of the same bits, so the sum is less than 2⋅2e−1−2⋅2s−1<2e2 \cdot 2^{e-1} - 2 \cdot 2^{s-1} < 2^e. Its highest possible bit is e−1e - 1, which is row ee. So the block, with its carry entering from below equal to 0, produces no carry into row e+1e + 1. By induction from the lowest block upward, the carry into each block is 0, and V+UV + U can be computed block by block.

Inside a block [s,e][s, e]. The block of VV has 1 bits at s,…,e−1s, \ldots, e - 1 and 0 at ee.

  • If UU has no bit in the block, that is, no row of [s,e−1][s, e - 1] is a match, then V+UV + U equals VV in the block: 1 at s,…,e−1s, \ldots, e - 1 and 0 at ee. V∧¬MV \wedge \neg M is 0 at ee, since VV is. So WW is 0 at row ee and 1 at rows s,…,e−1s, \ldots, e - 1. By Lemma 2, ff is ee or does not exist, and in both cases the only step is at ee. This matches.
  • If UU has a bit in the block, let ff be its lowest row; it is the first match in [s,e][s, e], since VV is 1 at all of s,…,e−1s, \ldots, e - 1. Adding the bit at row ff to the 1 bits at rows f,…,e−1f, \ldots, e - 1 makes them 0 and sets row ee. The other bits of UU, at rows in (f,e−1](f, e - 1], then fall on 0 bits and are set with no carry. So V+UV + U is 1 at rows s,…,f−1s, \ldots, f - 1, 0 at ff, equal to MM at rows f+1,…,e−1f + 1, \ldots, e - 1, and 1 at ee. The word V∧¬MV \wedge \neg M is 1 exactly at the rows of [s,e−1][s, e - 1] that are not matches. The OR is 1 at all rows of [s,e][s, e] except ff, where both terms are 0 (xf=yjx_f = y_j, and the sum is 0 there). By Lemma 2 the only step is at ff. This matches.

Final run [s,m][s, m]. If UU has no bit there, WW is all 1 in the run, and by Lemma 2 there is no step. Otherwise, with ff the lowest bit of UU, the carry from row ff runs through rows f,…,mf, \ldots, m and leaves the word, where the mod 2m2^m drops it; the rest is as in a block, without row ee. So WW is 1 at all rows of the run except ff, as Lemma 2 says.

Each row of WW therefore equals the row of EjE_j. □\square

Theorem. BIT-PARALLEL-LCS returns lcs(X,Y)\mathrm{lcs}(X, Y).

Proof. Line L1 builds the masks. Column 0 of the table is all 0, so it has no step, and E0=2m−1E_0 = 2^m - 1, which is line L2. By Lemma 4 and induction on jj, after round jj of line L3, V=EjV = E_j. After round nn, the number of 0 bits of VV is the number of steps of column nn, which is ∑i=1mδn(i)=c[m,n]−c[0,n]=c[m,n]\sum_{i=1}^m \delta_n(i) = c[m, n] - c[0, n] = c[m, n]. Line L6 returns mm minus the number of 1 bits, which is this number. ■\blacksquare

Cost. Each round does a constant number of operations on mm-bit words, each of which is ⌈m/w⌉\lceil m / w \rceil machine-word operations, with the carry of the addition passed from each machine word to the next. So the loop takes Θ(n⌈m/w⌉)\Theta(n \lceil m / w \rceil) time, and line L1 takes Θ(σ⌈m/w⌉+m)\Theta(\sigma \lceil m / w \rceil + m).

Back to Bit-parallel LCS algorithm