1
theory kmer_indexing encoding
Eric Coissac edited this page 2026-09-12 17:45:11 +02:00

DNA encoding

2-bit nucleotide encoding

Every nucleotide is encoded on 2 bits, most-significant-bit first within each word:

Base Encoding
A 00
C 01
G 10
T 11

The Watson-Crick complement of a base is its bitwise NOT on 2 bits: \text{complement}(base) = \lnot base \mathbin{\&} \texttt{0b11}.

Kmer encoding

A kmer of length k (k \le 31) fits in a single 64-bit word. The first nucleotide occupies the two most significant bits, each following nucleotide occupies the next two bits, and unused low-order bits are zero. Extracting nucleotide i (0-indexed from the 5′ end) is a shift-and-mask operation.

Reverse complement is computed by bit manipulation directly on the packed word, without any lookup table: complement every base, reverse the byte order, then reverse the order of 2-bit groups within each byte in two more passes, and finally realign the result to the most-significant bits.

Canonical form

The canonical form of a packed 2-bit sequence is the lexicographic minimum of the sequence and its reverse complement:

\text{canonical}(x) = \min\big(x,\ \text{revcomp}(x)\big)

This is a single operation on the packed representation, so it applies identically regardless of what x represents — a kmer (see Kmers), an m-mer (see Minimizer selection), or a super-kmer (see Super-kmers). Using the canonical form halves the relevant space and makes counting/selection strand-independent: a sequence and its reverse complement are always treated as the same entity, regardless of which DNA strand was sequenced.