字典树基础模板

 根据现在做的题而言,字典树对以下几个问题比较方便

1.查询字符串的信息(出现次数,前缀出现次数)

2.在一堆数中求异或最大值或者哪个数与此数异或最大。(多次求)

字典树在查询插入等操作的次数都为字符的长度,所以用起来很省时间  。

操作:

0.初始化字典树

1.插入[删除]

2.查询

 

字典树的每个节点可以代表一条根到该节点的路径。

/*
字典树
操作:
1.插入
3.查找
*/
#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
const int MAXN=10010;//单词的个数
const int ALPH=26;//字母表个数
typedef struct TireNode{
    TireNode* next[ALPH];
    int count;//表示该节点对应单词的个数
    TireNode()
    {
        count=0;
        for(int i=0;i<ALPH;++i)
            next[i]=NULL;
    };
} Node;
Node node[MAXN];
int top=0;
Node* root;
Node* CreatNode()
{
    Node* np=&node[top++];
    return np;
}
void InsertNode(Node* root,char *s)//字符串的根  字符串
{
    int len=strlen(s);
    Node *newp;
    newp=root;
    for(int i=0;i<len;++i)
    {
        if(newp->next[s[i]-'a']==NULL)
        {
            newp->next[s[i]-'a']=CreatNode();
        }
        newp=newp->next[s[i]-'a'];
    }
    newp->count+=1;
}
Node* searchNode(Node* root,char* s)//返回节点对应的地址
{
    int len=strlen(s);
    Node* newp;
    newp=root;
    for(int i=0;i<len;++i)
    {
        newp=newp->next[s[i]-'a'];
        if(!newp)
            return NULL;
    }
    return newp;
}
int main()
{
    top=0;
    root=&node[top++];
    int m;
    char s[30];
    scanf("%d",&m);
    while(m--)
    {
        scanf("%s",s);
        InsertNode(root,s);
    }
    int n;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",s);
        Node* midp;
        midp=searchNode(root,s);
        if(midp==NULL)
            cout<<0<<endl;
        else
         cout<<midp->count<<endl;
    }
}

每个节点有有一个指针数组,指向字母对应的下一个节点。若对应节点不存在,则p=null。

字典树模板二

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<cstdlib>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=500100;
struct Node
{
    int net[26];
    Node()
    {
        clear();
    }
    void clear()
    {
        memset(net,-1,sizeof(net));
    }
}node[maxn];
int top;
int hash_letter(char c)
{
    return c-'a';
}
void clear_tree(int &top)//清空树
{
    for(int i=0;i<=top;++i)
        node[i].clear();
    top=0;
}
void insert_node(char *s)//插入字符串
{
    int now=0;
    while(*s)//根据当前节点和字符选择该字符对应的节点
    {
        if(node[now].net[hash_letter(*s)]==-1)
        {
            node[now].net[hash_letter(*s)]=++top;
        }
        now=node[now].net[hash_letter(*s++)];
    }
}
int main()
{
    int n;
    char str[100];
    int maxlen;
    while(~scanf("%d",&n))
    {
        clear_tree(top);//初始化
        maxlen=-1;
        for(int i=0;i<n;++i)
        {
            scanf("%s",str);
            insert_node(str);
            maxlen=max(maxlen,(int)strlen(str));
        }
        printf("%d\n",2*top-maxlen+n);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值