目的:实现字符串快速检索
每个节点拥有若干个字符指针
空间换时间......
插入Insert void Insert(char *str) { int len = strlen(str); int root = 1; for(int k = 0;k < len; k++) { int ch = str[k] - 'a'; if(!trie[root][ch]) trie[root][ch] = ++tot; root = trie[root][ch]; } end[root] = 1; }
检索 int check(char *str) { int len = strlen(str), p = 1; for(int k = 0;k < len; k++) { p = trie[p][str[k] - 'a']; if(!p) return 0; } if(end[p]) return 1; else { end[p] = 1; return 2; } }
亦或的作用很多可以和trie树联系起来
这很显然
因为亦或的值可以在tri树上走相反数码
这就直接和亦或的最大最下联系起来了
亦或的性质还有一个
树上两个点的亦或值等于他们到根的亦或值的亦或值 -> *所以直接手动dfs 求出到根的亦或值 就ojbk了
其实并没有什么的......
就看字典树怎么套线段树什么的了 ....
例题 在给定的 NNN 个整数 A1,A2,…,ANA_1,A_2,…,A_NA1,A2,…,AN 中选出两个进行异或运算,得到的结果最大是多少?
思路 : 建树直接找相反亦或就OK了
#include<bits/stdc++.h> using namespace std; const int max_n = 3100010; int trie[max_n][2], tot = 1; int end[max_n]; int A[100010]; void Insert(int x) { int p = 1; for(int i = 30;~i; i--) { int c = (x >> i) & 1; if(!trie[p][c]) trie[p][c] = ++ tot; p = trie[p][c]; } end[p] = 1; } int check(int x) { int p = 1; int ans = 0; for(int i = 30;~i; i--) { int c = (x >> i) & 1; int ch = trie[p][c ^ 1]; if(!ch) { if(!trie[p][c]) return ans; p = trie[p][c]; continue; } ans += pow(2, i); p = trie[p][c ^ 1]; } return ans; } int main() { int n; scanf("%d", &n); int a; for(int i = 1;i <= n; i++) { scanf("%d", &A[i]); Insert(A[i]); } int Ans = -1; for(int i = 1;i <= n; i++) Ans = max(Ans, check(A[i])); cout << Ans; return 0; }