Find the maximum subarray XOR in a given array

geeksforgeeks的一篇文章:
http://www.geeksforgeeks.org/find-the-maximum-subarray-xor-in-a-given-array/

题目大意

给你一个大小为 N 的数组A,元素 0<=Ai<=231 ,即 Ai 是一个32位的非负整数。请寻找数组内异或和最大的连续子数组。注意:题目要求的是子数组,其中元素必须是连续的。

题目分析

最直接的方法是两层循环,找到所有子数组,并进行比较,时间复杂度为 O(N2)
另一种方法是“后缀数组+Trie字典树+贪心算法”。

后缀数组

定义 preXori=A1xorA2xor...xorAi ,那么数组 A 内任意子数组的异或和如下

resi,j=preXorixorpreXorj,i<=j

因此,我们需要找到数组 A 内所有的后缀子数组的异或和。然后,利用前面的数据,计算每个以Ai结束的异或和的最大值。

Trie字典树

为了方便寻找合适的后缀数组异或和,利用Trie字典存储每个后缀数组异或和 preXori preXori 以二进制(01)的形式存储到Trie中,因此该Trie也称为”01”字典树。从Trie的根往叶子节点的方向对应二进制 preXori 的高位到低位。例如 preXori=(5)10=(101)2 ,左数第一个1是高位,第二个1是低位。

该链接是一道Tire树的联系题:
http://blog.csdn.net/u010232171/article/details/43373697

贪心算法

完成上面两步后,开始计算以 Ai 结束子数组的最大异或和。思路是用已知的 preXori=A1xorA2...xorAi 作为Trie树的查询值。在查询过程中,力求找到与该值异或结果最大的值。遵循优先寻找对应二进制位上不同的节点(异或运算的特点 1xor0=1 )。这样,高位趋近1,结果就是最大的。

下面代码是geeksforgeeks上的内容

// C++ program for a Trie based O(n) solution to find max
// subarray XOR
#include<bits/stdc++.h>
using namespace std;

// Assumed int size
#define INT_SIZE 32

// A Trie Node
struct TrieNode
{
    int value;  // Only used in leaf nodes
    TrieNode *arr[2];
};

// Utility function tp create a Trie node
TrieNode *newNode()
{
    TrieNode *temp = new TrieNode;
    temp->value = 0;
    temp->arr[0] = temp->arr[1] = NULL;
    return temp;
}

// Inserts pre_xor to trie with given root
void insert(TrieNode *root, int pre_xor)
{
    TrieNode *temp = root;

    // Start from the msb, insert all bits of
    // pre_xor into Trie
    for (int i=INT_SIZE-1; i>=0; i--)
    {
        // Find current bit in given prefix
        bool val = pre_xor & (1<<i);

        // Create a new node if needed
        if (temp->arr[val] == NULL)
            temp->arr[val] = newNode();

        temp = temp->arr[val];
    }

    // Store value at leaf node
    temp->value = pre_xor;
}

// Finds the maximum XOR ending with last number in
// prefix XOR 'pre_xor' and returns the XOR of this maximum
// with pre_xor which is maximum XOR ending with last element
// of pre_xor.
int query(TrieNode *root, int pre_xor)
{
    TrieNode *temp = root;
    for (int i=INT_SIZE-1; i>=0; i--)
    {
        // Find current bit in given prefix
        bool val = pre_xor & (1<<i);

        // Traverse Trie, first look for a
        // prefix that has opposite bit
        if (temp->arr[1-val]!=NULL)
            temp = temp->arr[1-val];

        // If there is no prefix with opposite
        // bit, then look for same bit.
        else if (temp->arr[val] != NULL)
            temp = temp->arr[val];
    }
    return pre_xor^(temp->value);
}

// Returns maximum XOR value of a subarray in arr[0..n-1]
int maxSubarrayXOR(int arr[], int n)
{
    // Create a Trie and insert 0 into it
    TrieNode *root = newNode();
    insert(root, 0);

    // Initialize answer and xor of current prefix
    int result = INT_MIN, pre_xor =0;

    // Traverse all input array element
    for (int i=0; i<n; i++)
    {
        // update current prefix xor and insert it into Trie
        pre_xor = pre_xor^arr[i];
        insert(root, pre_xor);

        // Query for current prefix xor in Trie and update
        // result if required
        result = max(result, query(root, pre_xor));
    }
    return result;
}

// Driver program to test above functions
int main()
{
    int arr[] = {8, 1, 2, 12};
    int n = sizeof(arr)/sizeof(arr[0]);
    cout << "Max subarray XOR is " << maxSubarrayXOR(arr, n);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值