字典树(Trie树)
字典树(Trie Tree)
题目描述
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
输入格式
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
输出格式
对于每个提问,给出以该字符串为前缀的单词的数量.
输入样例
bananabandbeeabsoluteacmbabbandabc输出样例
2310
前不久学的Trie树,主要参考自这个巨佬的博客:Trie树傻瓜式入门+板子+经典例题
乱写一通笔记。
Trie树也叫字典树,又称单词查找树,是一种树形的数据结构,是哈希树的变种。主要运用于统计、排序和保存大量的字符串(但不仅限于字符串)。
它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
它主要长这样:
(下图为插入了字符串at、bee、ben、bt、q后的Trie树)
从这幅图里可以看出,Trie树的根节点是不包括字符的。也可以看出Trie树的主要思想。
代码(结合hduoj的例题使用):
#include <cstdio> #include <iostream> #include <cstring> #include <string> using namespace std; const int maxn=1e6+10; char s[maxn]; struct Trie{ int next[27]; int cnt; void init(){ cnt=0; memset(next,-1,sizeof next); } }node[maxn]; int qwq=1; void Insert(string s){ int p=0; for (int i=0;i<s.size();i++){ int temp=s[i]-'a'; if (node[p].next[temp]==-1){ //不存在该节点,则新建节点 node[qwq].init(); node[p].next[temp]=qwq; qwq++; //后移一位,指向下一个未知的节点 } p=node[p].next[temp]; //向下走,走到目前搜到的最后一个节点 node[p].cnt++; } } void query(string s){ //查询 int p=0; for (int i=0;i<s.size();i++){ int temp=s[i]-'a'; if (node[p].next[temp]==-1){ //不存在具有该前缀的字符串 printf("0\n"); return ; } p=node[p].next[temp]; } printf("%d\n",node[p].cnt); } int main(){ // freopen("test1.in","r",stdin); node[0].init(); string s; while (getline(cin,s)) if (s.size()==0) break; else Insert(s); while (getline(cin,s)) query(s); return 0; }
[学习自百度百科和其他网络资料]