一.介绍
前缀树又名字典树,单词查找树,Trie树,是一种多路树形结构,是哈希树的变种,和hash效率有一拼,是一种用于快速检索的多叉树结构。
缺点:内存消耗大。
二.静态二维数组实现
1.字典树的实现
#include <iostream>
using namespace std;
int cnt;
const int N=1000000;
int tree[N][26];
int pass[N];
int end1[N];
void build() {
cnt = 1;
}
void insert(string word) {
int cur = 1;
pass[cur]++;
int len=word.length();
for (int i = 0, path;i<len; i++) {
path = word[i] - '0';
if (tree[cur][path] == 0) {
tree[cur][path] = ++cnt;
}
cur = tree[cur][path];
pass[cur]++;
}
end1[cur]++;
}
bool search(string word) {
int cur = 1;
int len=word.length();
for (int i = 0, path; i<len; i++) {
path = word[i] - '0';
if (tree[cur][path] == 0) {
return 0;
}
cur = tree[cur][path];
}
return end1[cur]!=0;
}
int prefixnum(string word) {
int cur = 1;
int len=word.length();
for (int i = 0, path; i < len; i++) {
path = word[i] - '0';
if (tree[cur][path] == 0) {
return 0;
}
cur = tree[cur][path];
}
return pass[cur];
}
void delete_word(string word){
int cur=1;
int len=word.length();
for(int i=0,path;i<len;i++){
path=word[i]-'0';
if(--pass[tree[cur][path]]==0){
tree[cur][path]=0;
return;
}
cur=tree[cur][path];
}
end1[cur]--;
}
int main() {
int a,n;
string word;
build();
cin>>n;
while (n--) { // 注意 while 处理多个 case
cin>>a>>word;
if(a==1){
insert(word);
}else if(a==2){
delete_word(word);
}else if(a==3){
if(search(word)){
cout<<"YES"<<'\n';
}else{
cout<<"NO"<<'\n';
}
}else if(a==4){
cout<<prefixnum(word)<<'\n';
}
}
}
// 64 位输出请用 printf("%lld")
2.数组中两个数的最大异或结果
- 前缀树解法:
class Solution {
public:
int tree[1000000][2];
int cnt=1;
int maxindex=31;
void insert_num(vector<int> nums){
for(auto num:nums){
int cur=1;
for(int i=maxindex,path;i>=0;i--){
path=(num>>i)&1;
if(tree[cur][path]==0){
tree[cur][path]=++cnt;
}
cur=tree[cur][path];
}
}
}
int xorans(int num){
int cur=1;
int ans=0;
for(int i=maxindex,path,want;i>=0;i--){
path=(num>>i)&1;
want=path^1;
if(tree[cur][want]==0){
want^=1;
}
cur=tree[cur][want];
ans |=((want^path)<<i);
}
return ans;
}
int findMaximumXOR(vector<int>& nums) {
int max1=0;
for(auto num:nums){
max1=max(num,max1);
}
if(max1==0){
return 0;
}
while(((max1>>maxindex)&1)==0){
maxindex--;
}
insert_num(nums);
int ans=0;
for(auto num:nums){
ans=max(ans,xorans(num));
}
return ans;
}
};
- 哈希解法:
class Solution {
public:
unordered_set<int> myset;
int maxindex=31;
int findMaximumXOR(vector<int>& nums) {
int max1=0;
for(auto num:nums){
max1=max(num,max1);
}
if(max1==0){
return 0;
}
while(((max1>>maxindex)&1)==0){
maxindex--;
}
int ans=0;
for(int i=maxindex;i>=0;i--){
int better=ans | (1<<i);
for(auto num:nums){
num=(num>>i)<<i;
myset.insert(num);
if(myset.count(num^better)){
ans=better;
break;
}
}
myset.clear();
}
return ans;
}
};
3.表现良好的最长时间段
class Solution {
public:
int longestWPI(vector<int>& hours) {
int n=hours.size();
unordered_map<int,int> map;
map[0]=-1;
int sum=0;
int ans=0;
for(int i=0;i<n;i++){
int s=(hours[i]>8 ? 1:-1);
sum+=s;
if(sum>0){
ans=i+1;
}else{
if(map.count(sum-1))ans=max(ans,i-map[sum-1]);
}
if(map.count(sum)==0){
map[sum]=i;
}
}
return ans;
}
};