Purpose: String matching using bit-parallelism. Exact matching in (effectively when the pattern fits in a machine word), and β€” the reason it is famous β€” approximate matching with up to errors in . Also called shift-or, shift-and, or the Baeza-Yates-Gonnet algorithm.

Exact matching (shift-and form)

Precompute, for each character , a mask whose bit is 1 iff pattern[j] == c.

Maintain a state word where bit means β€œthe first characters of the pattern match a suffix of the text read so far”. The update per text character is a single shift and AND:

A match ends at position exactly when bit of is set.

Code

// exact match, pattern length <= 64
vector<int> bitap(const string& text, const string& pat) {
    int m = pat.size();
    if (m == 0 || m > 64) return {};
    array<uint64_t, 256> B{};
    for (int j = 0; j < m; j++) B[(unsigned char)pat[j]] |= 1ULL << j;
 
    vector<int> hits;
    uint64_t D = 0, msb = 1ULL << (m - 1);
    for (int i = 0; i < (int)text.size(); i++) {
        D = ((D << 1) | 1ULL) & B[(unsigned char)text[i]];
        if (D & msb) hits.push_back(i - m + 1);
    }
    return hits;
}

Approximate matching (up to errors)

Keep state words , where tracks partial matches with at most edits. Per text character:

uint64_t old = R[0];
R[0] = ((R[0] << 1) | 1) & B[c];
for (int d = 1; d <= k; d++) {
    uint64_t tmp = R[d];
    R[d] = ((R[d] << 1 | 1) & B[c])   // match
         | ((old | R[d-1]) << 1 | 1)  // substitution / insertion
         |  R[d-1];                   // deletion
    old = tmp;
}

A match with errors ends at when the top bit of is set.

Paradigm

Bit-parallel simulation of a nondeterministic automaton. The state word is the set of active NFA states; the shift is the transition, the AND is the character filter. Doing 64 states at once is where the speed comes from.

Complexity

  • Exact: time, space
  • Approximate:
  • Preprocessing:

When to use it

SituationBest tool
Exact match, long patternKMP or Z
Exact match, pattern ≀ 64, huge textBitap β€” extremely cache-friendly
Approximate match, small Bitap
Approximate match, generalFull edit distance DP, or Myers’ bit-vector algorithm
Many patterns at onceAho-Corasick

Variants / Use Cases

  • Shift-or vs shift-and β€” identical up to complementing the masks; shift-or avoids the | 1 at the cost of inverted logic
  • Myers’ bit-vector algorithm β€” computes full edit distance in , strictly stronger than Bitap for large
  • agrep / TRE / fuzzy searches β€” Bitap is the engine behind fuzzy grep tools
  • Wildcards and character classes β€” just set multiple bits in ; no algorithmic change needed
  • Bitset optimization β€” the general technique this exemplifies