字典树

字典树的插入以及询问

建立字典树

struct node
{
    int ch[26];//字典树编号为i时储存的字符在字典中与’a’的距离
    int end;//表示每一个字典树的叶子节点编号
} tree[maxn]; //tree【i】表示字典树的当前节点编号

int k=0,len;//注意我们对节点的编号要定义全局变量 不然每建立一次新树 我们的编号并没按照顺序来统计

void tree_insert(char *str)
{
    int len=strlen(str);
    int root=0,c,i;
    for(i=0; i<len; i++)
    {
        c=str[i]-'a';
        if(!tree[root].ch[c])
            tree[root].ch[c]=++k;
        root=tree[root].ch[c];
    }
    tree[root].end=1;
}

字典树的访问

int tree_query(char *ss)
{
    int qlen=strlen(ss);
    int root=0,i,c;
    for(i=0; i<qlen; i++)
    {
        c=ss[i]-'a';//注意:我们是用SS中的字符
        if(!tree[root].ch[c])//如果找不到编号为ROOT出发的边 说明SS字符串在整个字典树当中并没有出现
            return 0;
        root=tree[root].ch[c];//直接访问已经存在的字符串的编号进行继续访问
    }
    return tree[root].sum;
}

求解字符串在字典树中出现的次数

#include<bits/stdc++.h>

using namespace std;
const int maxn=2e6;

struct node
{
    int ch[26];//字典树编号为i的储存的字符在字典中与’a’的距离
    int sum;//长度为编号i的字符串出现的次数
} tree[maxn]; //tree【i】表示字典树的当前节点编号

int k=0,len;

void tree_insert(char *str)
{
    int len=strlen(str);
    int root=0,c,i;
    for(i=0; i<len; i++)
    {
        c=str[i]-'a';
        if(!tree[root].ch[c])
            tree[root].ch[c]=++k;
        root=tree[root].ch[c];
        tree[root].sum++;
    }
}
int tree_query(char *ss)
{
    int qlen=strlen(ss);
    int root=0,i,c;
    for(i=0; i<qlen; i++)
    {
        c=ss[i]-'a';
        if(!tree[root].ch[c])
            return 0;
        root=tree[root].ch[c];
    }
    return tree[root].sum;
}
int main()
{
    char str[30];
    while (gets(str) && strlen(str))
    {
        tree_insert(str);
    }
    while (gets(str))
        printf("%d\n", tree_query(str));
    return 0;
}

0—1字典树(选择静态 动态 哪位路过大佬知道留言呗)

int tree[32 * maxn][2], val[32 * maxn], tot;//只是一个基本模板 后续更新/静态

void Insert(ll n)
{
    int root = 0;
    for (int i = 32; i >= 0; i--)
    {
        int id = (n >> i) & 1;
        if (!tree[root][id])
            tree[root][id] = ++tot;
        root = tree[root][id];
    }
    val[root] = n;
}

ll get_ans(ll n)
{
    int root = 0;
    for (int i = 32; i >= 0; i--)
    {
        int id = (n >> i) & 1;
        if (tree[root][id ^ 1])
            root = tree[root][id ^ 1];
        else
            root = tree[root][id];
    }
    return val[root];
}
const int maxn=2e5;/动态模板

struct node
{
    int ch[2];//字典树编号为i的储存边(二进制的0 OR 1)
    LL val;//储存数
} tree[maxn]; //tree【i】表示字典树的当前节点编号

int k;
LL x[maxn];
void tree_insert(LL x)
{
    int i,root=0;
    for(i=32;i>=0;i--)
    {
        int c=(x>>i)&1;//把该数从高位开始的0 OR 1计算出来
        if(!tree[root].ch[c])
            tree[root].ch[c]=++k;
        root=tree[root].ch[c];
    }
    tree[root].val=x;
}
LL tree_query(LL x)
{
    int i,root=0;
    for(i=32;i>=0;i--)
    {
        int c=(x>>i)&1;//采用贪心的策略 先从最高位开始找和1亦或的节点
        if(tree[root].ch[c^1])
            root=tree[root].ch[c^1];
        else
            root=tree[root].ch[c];
    }
    return tree[root].val;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值