字符串与二进制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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞