字符串与二进制Trie树的简单模板

字符串的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;
}

 

    原文作者:Trie树
    原文地址: https://blog.csdn.net/WWWengine/article/details/82385792
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞