字符串的Trie树:
Description
给出n个单词组成的字典(可能由相同的单词),请你完成下列任务:
任务1、把n个单词去重后按字典序由小到大后输出。
任务2、给出m个询问,每次询问一个单词是否在字典中存在,如果存在,输出该单词在字典中出现的次数。
Input
第一行为n和m。接下来的n行,每行一个单词。中间空一行。在接下来的m行,每行一个单词,表示一个询问。
Output
开始的n行为任务1的输出结果。空一行后输出m行,每行一个整数,表示询问的结果(不存在,则输出0)。
设ch[i][d]表示节点i的d号节点编号,0<=d<52,分别对应a~z,A~Z,其实就是把大小写的26个字母对应成数字。val[i]表示有多少个单词在i节点结束。缺点是空间不够理想。(有些裸题不如用map…)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=100005;
int val[MAXN*52];
int ch[MAXN][52];
int rt=0,np=0;
char s[55];
int idx(char c)
{
if(c>='A'&&c<='Z') return c-'A';
return c-'a'+26;
}
char idc(int x)
{
if(x>=0&&x<=25) return x+'A';
return x-26+'a';
}
void insert(int &now,char *s,int i)
{
if(!now) now=++np;
if(s[i]=='\0')
{
val[now]++;
return;
}
insert(ch[now][idx(s[i])],s,i+1);
}
void dfs(int now,int i)
{
if(val[now])
{
s[i]='\0';
printf("%s\n",s);
}
for(int d=0;d<52;d++)
{
if(ch[now][d])
{
s[i]=idc(d);
dfs(ch[now][d],i+1);
}
}
}
int query(int now,char *s)
{
for(int i=0;s[i]!='\0';i++)
{
int d=idx(s[i]);
now=ch[now][d];
if(!now) return 0;
}
return val[now];
}
int main()
{
int N,M;
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
{
scanf("%s",s);
insert(rt,s,0);
}
dfs(rt,0); putchar('\n');
while(M--)
{
scanf("%s",s);
printf("%d\n",query(rt,s));
}
return 0;
}
二进制的Trie树:
题目描述
给出n个非负整数A[1]..A[n],编程回答询问:x:询问 max {x xor A[i] | 1<=i<=n}的值。
输入
第一行为整数n。第二行为n个非负整数,表示A[1],A[2],…,A[n]。第三行为整数m。之后的m行,每行表示一种询问:x
输出
对于每个询问,给出你的回答。
这里数据范围是unsigned long long ,因此二进制最多可分解出64位。空间相比字符串好一些。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef unsigned long long ULL;
const int MAXN=100005;
int ch[MAXN*64][2];
int rt=0,np=0;
char c;
void scan(int &x)
{
for(c=getchar();c<'0'||c>'9';c=getchar());
for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}
void scan(ULL &x)
{
for(c=getchar();c<'0'||c>'9';c=getchar());
for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}
char num[30];int ct;
void print(ULL x)
{
ct=0;
if(!x) num[ct++]='0';
while(x) num[ct++]=x%10+'0',x/=10;
while(ct--) putchar(num[ct]);
putchar('\n');
}
void insert(int &now,ULL x,int i)
{
if(!now) now=++np;
if(i<0) return;
insert(ch[now][(x>>i)&1],x,i-1);
}
ULL query(int now,ULL x,int i)
{
if(i<0) return 0;
int d=(x>>i)&1;
if(ch[now][1^d]) return query(ch[now][1^d],x,i-1)+((ULL)1<<i);
return query(ch[now][d],x,i-1);
}
int main()
{
int N,M; ULL x;
scan(N);
for(int i=1;i<=N;i++)
{
scan(x);
insert(rt,x,63);
}
scan(M);
while(M--)
{
scan(x);
print(query(rt,x,63));
}
return 0;
}