Patterns/Part VIII - Cross-Topic Deep Dives/XOR Basis / Linear Basis

Pattern Reference

XOR Basis / Linear Basis

"Basis of numbers under XOR. Maximum XOR subset, minimum XOR subset, K-th smallest XOR, rank of XOR space."

Loading...

Deep Dive Tutorial

An XOR linear basis stores at most 30-60 numbers (one per bit) such that any XOR combination of the original array equals some XOR combination of basis elements. Insert: for each number, try to reduce it using existing basis elements from high bit to low. If it reduces to 0, it's linearly dependent (already representable). If not, add it at its highest bit position.

XOR linear basis template
class XorBasis {
    constructor() { this.basis = new Array(30).fill(0); this.size = 0; }

    insert(x) {
        for (let i = 29; i >= 0; i--) {
            if (!((x >> i) & 1)) continue; // bit i not set
            if (!this.basis[i]) { this.basis[i] = x; this.size++; return true; }
            x ^= this.basis[i]; // reduce by existing basis element
        }
        return false; // x was 0 after reduction → linearly dependent
    }

    // Maximum XOR achievable using any subset
    maxXor() {
        let res = 0;
        for (let i = 29; i >= 0; i--) res = Math.max(res, res ^ this.basis[i]);
        return res;
    }

    // Minimum non-zero XOR achievable (lowest bit basis element)
    minXor() {
        for (let i = 0; i <= 29; i++) if (this.basis[i]) return this.basis[i];
        return 0;
    }

    // k-th smallest XOR value (1-indexed, must reduce basis to row echelon form first)
    // First reduce: for each i from low to high, reduce higher basis elements
    kthSmallest(k) {
        const reduced = [];
        for (let i = 0; i <= 29; i++) {
            if (!this.basis[i]) continue;
            let v = this.basis[i];
            for (let j = i - 1; j >= 0; j--) if ((v >> j) & 1) v ^= this.basis[j];
            reduced.push(v);
        }
        // Now reduced[i] corresponds to bit i of k
        let res = 0;
        for (let i = 0; i < reduced.length; i++) if ((k >> i) & 1) res ^= reduced[i];
        return res;
    }
}

Worked Problems

XOR basis key properties:
- At most 30 elements (one per bit for 32-bit integers)
- Spans the same XOR closure as the original set
- Any number representable as XOR of subset iff it reduces to 0 during insertion

Max XOR algorithm: Greedily try to set each bit from high to low: if XOR-ing with basis element increases current result, do it.

Count distinct XOR values: 2^(basis.size) distinct values possible (including 0).

Merge two bases: Insert all elements of one into the other — O(30²) per merge.

Online vs offline: Basis supports online insertions. For "max XOR with elements ≤ limit," sort and insert offline.