Trie树(又叫前缀树或字典树)是一种树形结构,专门用于高效地存储和查找字符串集合,特别适合处理前缀相关问题,如自动补全、字符串匹配、前缀计数等。
代码模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
int son[N][N],cnt[N],idx;
void insert(const char *str) { int p=0; for(int i=0;str[i];i++) { int u=str[i]-'a'; if(!son[p][u])son[p][u]=++idx; p=son[p][u]; } cnt[p]++; }
int query(const char *str) { int p=0; for(int i=0;str[i];i++) { int u=str[i]-'a'; if(!son[p][u])return 0; p=son[p][u]; } return cnt[p]; }
|
一道经典题目:最大异或数
在给定的 N 个整数 A1,A2……AN 中选出两个进行 xor(异或)运算,得到的结果最大是多少?
输入格式
第一行输入一个整数 N。
第二行输入 N 个整数 A1~AN。
输出格式
输出一个整数表示答案。
数据范围
1≤N≤105,
0≤Ai<231
分析:很明显,需要把每一个整数拆成32位,然后逐步插入Trie树(这里就只有0和1两种了),所有处理完之后,我们对每一个数去找可能最大的异或数,然后取所有的最大值就好了。
具体如果找异或数呢,其实也就是遍历数的过程,如果有跟当前位相反的,就直接取,否则就只能取0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include<iostream> #include<vector> using namespace std; const int N=32*1e5+10; int son[N][2],idx; void insert(int x) { int p=0; for(int i=31;i>=0;i--) { int bit=(x>>i)&1; if(!son[p][bit])son[p][bit]=++idx; p=son[p][bit]; } } int main() { int n;scanf("%d",&n); vector<int>nums; for(int i=0;i<n;i++){ int x;scanf("%d",&x); insert(x);nums.push_back(x); } int ans=0; for(int x:nums) { int sum=0;int p=0; for(int i=31;i>=0;i--) { int bit=(x>>i)&1; int op=bit^1; if(son[p][op]) { sum|=(1<<i); p=son[p][op]; } else p=son[p][bit]; } ans=max(ans,sum); } printf("%d",ans); }
|