1. 程式人生 > >Find the maximum subarray XOR in a given array

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內所有的字尾子陣列的異或和。然後,利用前面的資料,計算每個以A
i
結束的異或和的最大值。

Trie字典樹

為了方便尋找合適的字尾陣列異或和,利用Trie字典儲存每個字尾陣列異或和preXoripreXori以二進位制(01)的形式儲存到Trie中,因此該Trie也稱為”01”字典樹。從Trie的根往葉子節點的方向對應二進位制preXori的高位到低位。例如preXori=(5)10=(101)2,左數第一個1是高位,第二個1是低位。

貪心演算法

完成上面兩步後,開始計算以Ai結束子陣列的最大異或和。思路是用已知的preXori=A1xorA2...xorAi作為Trie樹的查詢值。在查詢過程中,力求找到與該值異或結果最大的值。遵循優先尋找對應二進位制位上不同的節點(異或運算的特點1

xor0=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; }