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字典存儲每個後綴數組異或和preXoripreXori 以二進制(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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章