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
| Situation | Best tool |
|---|---|
| Exact match, long pattern | KMP or Z |
| Exact match, pattern β€ 64, huge text | Bitap β extremely cache-friendly |
| Approximate match, small | Bitap |
| Approximate match, general | Full edit distance DP, or Myersβ bit-vector algorithm |
| Many patterns at once | Aho-Corasick |
Variants / Use Cases
- Shift-or vs shift-and β identical up to complementing the masks; shift-or avoids the
| 1at the cost of inverted logic - Myersβ bit-vector algorithm β computes full edit distance in , strictly stronger than Bitap for large
agrep/TRE/fuzzysearches β 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