Subarray with XOR less than k

Given an array of n numbers and a number k. You have to write a program to find the number of subarrays with xor less than k.

Examples:

Input:  arr[] = {8, 9, 10, 11, 12},  k=3
Output: 4
Sub-arrays [1:3], [2:3], [2:5], [4:5] have xor 
values 2, 1, 0, 1 respectively.

Input: arr[] = {12, 4, 6, 8, 21},  k=8
Output: 4

Naive Approach: The naive algorithm is to simply calculate the xor value of each and every subarray and compare with the given number k to find the answer.

Below is implementation of this approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to count number of
// subarrays with XOR less than k
#include <iostream>
using namespace std;
  
// function to count number of
// subarrays with XOR less than k
int xorLessK(int arr[], int n, int k)
{
    int count = 0;
  
    // check all subarrays
    for (int i = 0; i < n; i++) {
        int tempXor = 0;
        for (int j = i; j < n; j++) {
            tempXor ^= arr[j];
            if (tempXor < k)
                count++;
        }
    }
  
    return count;
}
  
// Driver program to test above function
int main()
{
    int n, k = 3;
    int arr[] = { 8, 9, 10, 11, 12 };
  
    n = sizeof(arr) / sizeof(arr[0]);
  
    cout << xorLessK(arr, n, k);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to count number of 
// subarrays with XOR less than k 
  
import java.io.*;
  
class GFG {
      
// function to count number of 
// subarrays with XOR less than k 
static int xorLessK(int arr[], int n, int k) 
    int count = 0
  
    // check all subarrays 
    for (int i = 0; i < n; i++) { 
        int tempXor = 0
        for (int j = i; j < n; j++) { 
            tempXor ^= arr[j]; 
            if (tempXor < k) 
                count++; 
        
    
  
    return count; 
  
// Driver program to test above function 
    public static void main (String[] args) {
  
          
    int k = 3
    int arr[] = new int[] { 8, 9, 10, 11, 12 }; 
    int n = arr.length; 
  
    System.out.println(xorLessK(arr, n, k)); 
          
    }
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 program to count number of
# subarrays with XOR less than k
  
# function to count number of
# subarrays with XOR less than k
def xorLessK(arr, n, k):
    count = 0
  
    # check all subarrays
    for i in range(n):
        tempXor = 0
        for j in range(i, n):
            tempXor ^= arr[j]
            if (tempXor < k):
                count += 1
      
    return count
  
# Driver Code
if __name__ == '__main__':
    k = 3
    arr = [8, 9, 10, 11, 12]
  
    n = len(arr)
  
    print(xorLessK(arr, n, k))
  
# This code is contributed by
# Sahil_shelangia

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to count number of 
// subarrays with XOR less than k 
using System;
  
class GFG {
      
// function to count number of 
// subarrays with XOR less than k 
static int xorLessK(int []arr, int n, int k) 
    int count = 0; 
  
    // check all subarrays 
    for (int i = 0; i < n; i++) { 
          
        int tempXor = 0; 
          
        for (int j = i; j < n; j++) { 
              
            tempXor ^= arr[j]; 
            if (tempXor < k) 
                count++; 
        
    
  
    return count; 
  
// Driver Code
static public void Main ()
{
          
    int k = 3; 
    int []arr = new int[] {8, 9, 10,
                           11, 12 }; 
    int n = arr.Length; 
    Console.WriteLine(xorLessK(arr, n, k)); 
      

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// PHP program to count number of
// subarrays with XOR less than k
  
// function to count number of
// subarrays with XOR less than k
function xorLessK($arr, $n, $k)
{
    $count = 0;
  
    // check all subarrays
    for ($i = 0; $i < $n; $i++) 
    {
        $tempXor = 0;
        for ($j = $i; $j < $n; $j++)
        {
            $tempXor ^= $arr[$j];
            if ($tempXor < $k)
                $count++;
        }
    }
  
    return $count;
}
  
    // Driver Code
    $n; $k = 3;
    $arr = array(8, 9, 10, 11, 12);
  
    $n = count($arr);
  
    echo xorLessK($arr, $n, $k);
  
// This code is contributed by anuj_67.
?>

chevron_right



Output:

3

Time Complexity: O(n^2).

Efficient Approach: An efficient approach will be to calculate all of the prefix xor values i.e. a[1:i] for all i.
It can be verified that the xor of a subarray a[l:r] can be written as (a[1:l-1] xor a[1:r]), where a[i, j] is the xor of all the elements with index such that, i <= index <= j.
Explanation:
We will store a number as binary number in trie. The left child will shows that the next bit is 0 and the right child will show the next bit is 1.
For example, given picture below shows number 1001 and 1010 in trie.
trie1

If xor[i, j] represents the xor of all elements in the subarray a[i, j], then at an index i what we have is, a trie which has xor[1:1], xor[1:2]…..xor[1:i-1] already inserted. Now we somehow count how many of these (numbers in trie) are such that its xor with xor[1:i] is smaller than k. This will cover all the subarrays ending at the index i and having xor i.e. xor[j, i] <=k;

Now the problem remains, how to count the numbers with xor smaller than k. So, for example take the current bit of the ith index element is p, current bit of number k be q and the current node in trie be node.
Take the case when p=1, k=1. Then if we go to the right child the current xor would be 0 (as the right child means 1 and p=1, 1(xor)1=0).As k=1, all the numbers that are to the right child of this node would give xor value smaller than k. So, we would count the numbers that are right to this node.
If we go to the left child, the current xor would be 1 (as the left child means 0 and p=1, 0(xor)1=1). So, if we go to the left child we can still find number with xor smaller than k, therefore we move on to the left child.

So, to count the numbers that are below a given node, we modify the trie and each node will also store the number of leafs in that subtree and this would be modified after each insertion.

Other three cases for different values of p and k can be solved in the same way to the count the number of numbers with xor less than k.

Below is the C++ implementation of above idea:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to efficiently count number of
// subarrays with XOR less than k
#include <bits/stdc++.h>
using namespace std;
  
// trie node
struct node
{
    struct node* left;
    struct node* right;
    struct node* parent;
    int leaf = 1;
};
  
// head node of trie
struct node* head = new node;
  
// initializing a new node
void init(node* temp)
{
    temp->left = NULL;
    temp->right = NULL;
    temp->parent = NULL;
    temp->leaf = 1;
}
  
// updating the leaf count of trie
// nodes after insertion
void update(node* root)
{
    // updating from bottom to
    // top (leaf to root)
    if (root->right && root->left) // sum of left and right
        root->leaf = root->right->leaf + root->left->leaf;
    else if (root->left) // only the left
        root->leaf = root->left->leaf;
    else if (root->right) // only the right
        root->leaf = root->right->leaf;
  
    if (root->parent) // updating the parent
        update(root->parent);
}
  
// function to insert a new
// binary number in trie
void insert(string num, int level, node* root)
{
    // if added the last node updates the
    // leaf count using update function
    if (level == -1)
    {
        update(root);
        return;
    }
  
    // conversion to integer
    int x = num[level] - '0';
    if (x == 1)
    {
        // adding a right child
        if (!root->right)
        {
            struct node* temp = new node;
            init(temp);
            root->right = temp;
            temp->parent = root;
        }
  
        // calling for the right child
        insert(num, level - 1, root->right);
    }
    else
    {
  
        // adding a left child
        if (!root->left)
        {
            struct node* temp = new node;
            init(temp);
            root->left = temp;
            temp->parent = root;
        }
  
        // calling for the left child
        insert(num, level - 1, root->left);
    }
}
  
// Utility function to find the number of
// subarrays with xor less than k
void solveUtil(string num, string k, int level,
               node* root, int& ans)
{
    if (level == -1)
        return;
  
    if (num[level] == '1')
    {
  
        // numbers in the right subtree
        // added to answer
        if (k[level] == '1')
        {
            if (root->right)
                ans += root->right->leaf;
            if (root->left)
                solveUtil(num, k, level - 1, root->left, ans);
        }
        else
        {
            if (root->right)
                solveUtil(num, k, level - 1, root->right, ans);
        }
  
    }
    else
    {
        if (k[level] == '0')
        {
            if (root->left)
                solveUtil(num, k, level - 1, root->left, ans);
        }
        else   // then the numbers in the left
        {
            // subtree added to answer
            if (root->left)
                ans += root->left->leaf;
            if (root->right)
                solveUtil(num, k, level - 1, root->right, ans);
        }
    }
}
  
// function to find the number of
// subarrays with xor less than k
int solve(int a[], int n, int K)
{
    int maxEle = K;
  
    // Calculate maximum element in array
    for (int i = 0; i < n; i++)
        maxEle = max(maxEle, a[i]);
  
    // maximum height of the Trie when
    // the numbers are added as binary strings
    int height = (int)ceil(1.0 * log2(maxEle)) + 1;
  
    // string to store binary
    // value of K
    string k = "";
  
    int temp = K;
  
    // converting go to binary string and
    // storing in k
    for (int j = 0; j < height; j++)
    {
        k = k + char(temp % 2 + '0');
        temp /= 2;
    }
  
    string init = "";
    for (int i = 0; i < height; i++)
        init += '0';
  
    // adding 0 to the trie(initial value)
    insert(init, height - 1, head);
  
    int ans = 0;
    temp = 0;
    for (int i = 0; i < n; i++)
    {
        string s = "";
        temp = (temp ^ a[i]);
  
        // converting the array element to binary string s
        for (int j = 0; j < height; j++)
        {
            s = s + char(temp % 2 + '0');
            temp = temp >> 1;
        }
  
        solveUtil(s, k, height - 1, head, ans);
  
        insert(s, height - 1, head);
    }
  
    return ans;
}
  
// Driver program to test above function
int main()
{
    init(head); // initializing the head of trie
  
    int n = 5, k = 3;
  
    int arr[] = { 8, 9, 10, 11, 12 };
  
    cout << solve(arr, n, k) << endl;
  
    return 0;
}

chevron_right


Output:

4

Time complexity: O(n*log(max)), where max is the maximum element in the array.

Related Articles:

This article is contributed by Amritya Vagmi. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.



My Personal Notes arrow_drop_up

Improved By : vt_m, jit_t, sahilshelangia



Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.