标签:mat tar 等等 star void nod style pac nullptr
异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法。
前缀树详解:https://www.cnblogs.com/tianzeng/p/10584650.html
#include <iostream> #include <vector> #include <cmath> using namespace std; //1.暴力解O(n^3) int get_max_eor(const vector<int>& arr) { if(arr.empty()||arr.size()<0) return -1; int Max=-0x3f3f; for(unsigned int i=0;i<arr.size();++i)//以i结尾的每个子数组 { for(unsigned int start=0;start<=i;++start)//0..i/1..i/2..i等等,前两个for找所有的子数组 { int Eor=0; for(unsigned int k=start;k<=i;++k)//遍历每个区间:k=[start..i],求每个区间的最大异或和,arr.at(k) Eor^=(arr.at(k)); Max=max(Max,Eor); } } return Max; } //2.记忆化优化解O(n^2) //0...i异或结果为Sum //0...start-1异或结果为A //start...i的异或结果为Sum^A int get_max_eor1(const vector<int>& arr) { if(arr.size()<0||arr.empty()) return -1; int Eor=0; int Max=-0x3f3f; for(unsigned int i=0;i<arr.size();++i) { Eor^=arr.at(i);//遍历0...i,Xor保存每个以i结尾的最长数组的异或和 Max=max(Max,Eor);//一:可能是整个以i结尾的数组的异或和最大 int res=0; for(unsigned int start=0;start<=i;++start) { res^=arr.at(start);//每个以i结尾的数组的前半部分 Max=max(Max,res^Eor);//二:可能是某个子数组的异或和最大 } } return Max; } //2 O(n^2) int get_max_eor2(const vector<int>& arr) { if(arr.size()<0||arr.empty()) return -1; vector<int> dp(arr.size(),0); int Eor=0; int Max=-0x3f3f; for(unsigned int i=0;i<arr.size();++i) { Eor^=arr.at(i); Max=max(Max,Eor); for(unsigned int start=1;start<=i;++start) { int res=Eor^dp[start-1]; Max=max(Max,res); } dp.at(i)=Eor; } return Max; } //3 //0...i的异或结果Eor存 //0...0异或结果 0...1的异或结果 0...2的异或结果 直到0...i-1的异或结果(装入黑盒---前缀树) typedef struct Node { Node *next[2]; Node() { next[0]=nullptr; next[1]=nullptr; } }Node; class Trie { public: int get_max_eor3(const vector<int>& arr); ~Trie() { delete head; } private: int max_eor(const int &num); void add(const int &num); static Node *head; }; Node* Trie::head=new Node(); int Trie::get_max_eor3(const vector<int>& arr) { if(arr.size()<0||arr.empty()) return -1; int Max=-0x3f3f; int Eor=0; Trie trie; trie.add(0); for(unsigned int i=0;i<arr.size();++i) { Eor^=arr.at(i); Max=max(max_eor(Eor),Max); add(Eor); } return Max; } void Trie::add(const int& num)//把num添加到前缀树中 { Node *cur=head; int res=0; for(int move=31;move>=0;--move) { int path=((num>>move)&1);//取每一位 cur->next[path]=(cur->next[path]==nullptr?new Node():cur->next[path]); cur=cur->next[path]; } } //符号位尽量为0,后面的位是0走1,1走0,没得选就将就着走,尽量保持最大化值 //每次选最优,可以找到最大值 int Trie::max_eor(const int& num)//num和前缀树中的哪个值异或和最大 { int res=0; Node *cur=head; for(int move=31;move>=0;--move) { int path=((num>>move)&1); int best=(move==31?path:(path^1)); best=(cur->next[best]!=nullptr?best:(best^1)); res|=((path^best)<<move); cur=cur->next[best]; } return res; } int main() { vector<int> arr{1,2,3,5,6,8,9}; cout<<get_max_eor(arr)<<endl; cout<<get_max_eor1(arr)<<endl; cout<<get_max_eor2(arr)<<endl; Trie t; cout<<t.get_max_eor3(arr)<<endl; return 0; }
标签:mat tar 等等 star void nod style pac nullptr
原文地址:https://www.cnblogs.com/tianzeng/p/10584668.html