又称单词查找树,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;
}