Bitmask as a Set
When the universe of values is small - 26 letters, n <= 32, a fixed alphabet - a single integer is a set. Bit x is set exactly when element x is present.
| Operation | Expression | Cost |
|---|---|---|
add x | mask |= 1 << x | O(1) |
remove x | mask &= ~(1 << x) | O(1) |
test x | mask & (1 << x) | O(1) |
toggle x | mask ^= 1 << x | O(1) |
| union / intersection | a | b / a & b | O(1) |
| size | mask.bit_count() | O(1) |
| is complete | mask == (1 << n) - 1 | O(1) |
Every one of those is a single CPU instruction, with no hashing, no allocation, and no pointer chasing. A set does the same job in the same asymptotic time but hundreds of times slower in constant factor, and it cannot be compared, unioned, or used as a dictionary key for free.
The tell that a problem wants a bitmask: "contains only characters from", "collect all of 1..k", "which elements appear in both", or any subset-of-a-small-universe question.
Sets as Bitmasks
Build one mask per group, then answer the question with a single operator. Containment is word_mask & ~allowed == 0. Membership in both arrays is a & b. Completeness is a comparison against the all-ones mask. Duplicate detection is a test-then-set.