字典树(Tire树)模板+例题

又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
将给定的字符串建立为空根数,然后在节点中做相应记录,如到当前前缀串为止的子串。
这里写图片描述
上面的数就是由字符串 abcd,abd,bcd,efg,hij最右边的j图的原因掉了,建成数之后再查询,一旦第一个字符不匹配,其子树就可以不再遍历,所以大大的节省了时间,
节点结构如下

#define SIZE 26
typedef struct Node{
    //指定每一个节点都可能有26个子节点 
    Node *next[SIZE];
    //以当前串前缀的单词总数 
    int count; 
} Node;

当然26只对于a-z或者A-Z,可以根据字符串中包含的字符进行调整,
结合例题来看,模板裸题
hdu1251,求某前缀下的单词数,给出文章建树,给出前缀查询。
统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 39169 Accepted Submission(s): 14269

Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).

Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

注意:本题只有一组测试数据,处理到文件结束.

Output
对于每个提问,给出以该字符串为前缀的单词的数量.

Sample Input

banana
band
bee
absolute
acm

ba
b
band
abc

Sample Output

2
3
1
0
模板题,所以代码就属于是字典树的模板代码。

/*
    字典树解决字符串前缀问题 
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 26
typedef struct Node{
    //指定每一个节点都可能有26个子节点 
    Node *next[SIZE];
    //以当前串前缀的单词总数 
    int count; 
} Node;

//创建节点。 
Node * createNode()
{
    Node *node = (Node *)malloc(sizeof(Node));
    //初始化节点 
    node->count = 0;
    memset(node->next,0,sizeof(node->next));

    return node; 
} 
//给出字符串,分解字符建树 
void insert(Node *root,char *str)
{
    Node *p = root;
    char *q = str;
    int id;
    while(*q)
    {
        id = *q-'a';
        if(p->next[id]==NULL)
        {
            p->next[id] = createNode(); 
        }   
        p = p->next[id];
        //继续向下指 
        ++q;
        p->count+=1;
    }
} 
//给出前缀,分解前缀串查询
int search(Node *root,char *str)
{
    Node *p = root;
    char *q = str;
    int id;
    while(*q)
    {
        id = *q-'a';
        p = p->next[id];
        ++q;
        if(p==NULL)
        {
            return 0;
        }
    } 
    return p->count;
} 

int main()
{
    Node *root = createNode();
    char str[12];
    bool flag=false;
    while(gets(str))
    {
        if(flag)
        {
            printf("%d\n",search(root,str));
        }
        else{
            if(strlen(str)!=0)
            {
                insert(root,str);
            }
            else
            {
                flag=true;
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值