字典树(Trie树)总结-hdu1251
2017-05-01 16:20
155 查看
字典树(也称前缀树,Trie)
Trie树,又称单词查找树、字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。Trie高效的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提率的目的。
它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
Trie树也有它的缺点,Trie树的内存消耗非常大。
三个基本特性:
1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3. 每个节点的所有子节点包含的字符都不相同。
应用:
1. 字符串检索,词频统计,搜索引擎的热门查询
2. 字符串最长公共前缀
Trie树利用多个字符串的公共前缀来节省存储空间,反之,当我们把大量字符串存储到一棵trie树上时,我们可以快速得到某些字符串的公共前缀。
举例:给出N 个小写英文字母串,以及Q 个询问,即询问某两个串的最长公共前缀的长度是多少.
解决方案:
首先对所有的串建立其对应的字母树。此时发现,对于两个串的最长公共前缀的长度即它们所在结点的公共祖先个数,于是,问题就转化为了离线 (Offline)的最近公共祖先(Least Common Ancestor,简称LCA)问题。
3. 排序:Trie树是一棵多叉树,只要先序遍历整棵树,输出相应的字符串便是按字典序排序的结果。
我以hdu1251为例,写一个Trie树的模板。
hdu1251
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251题意:老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀)。
这题有个小技巧。
如何判断空行:用gets()读入。读入的回车符会自动转换为NULL。所以循环读入,每次检测读入进来的字符串的第一个字符是否为NULL即可。
没什么题解,这题可以说是Trie树的模板题,直接Trie树解决就行了。
代码有两种,一种用链表实现,一种用数组实现,数组做法在时间和空间上都优于链表。(推荐用数组,链表理解简单些)
先看链表代码,简单理解一下,再看数组代码就轻松些。
链表代码
//当前代码并不能过,编译器从g++改为c++,交g++的话会超内存。 //原因好像是g++会优化,导致出现一些问题。感兴趣的自行百度。 //c++编译器不支持#include <bits/stdc++.h>,所以再把该头文件改为其它即过 //#include <bits/stdc++.h>包含所有头文件,你把它删掉写具体的头文件出来就OK #include <bits/stdc++.h> using namespace std; struct Trie{ Trie *next[26]; //每个节点可以延伸26个子节点,即a-z int num; //含有当前前缀的单词个数 Trie() //初始化 { for(int i=0;i<26;i++) next[i]=NULL; num=0; } }root; int idx(char s) //字母转数字 { return s-'a'; } void Trie_insert(char word[]) //插入单词 { Trie *p=&root; for(int i=0;word[i];i++) { //如果不存在当前前缀就新建 if(p->next[idx(word[i])]==NULL) p->next[idx(word[i])] = new Trie; p = p->next[idx(word[i])]; //节点移到当前前缀 p->num++; //含有当前前缀的单词+1 } } int Trie_search(char word[]) //查询存在以word[]为前缀的单词个数 { Trie *p=&root; for(int i=0;word[i];i++) //找到前缀为word[]的节点 { if(p->next[idx(word[i])]==NULL) return 0; p = p->next[idx(word[i])]; } return p->num; } int main() { char word[11]; while(cin.getline(word,11)) { if(strlen(word)==0) break; Trie_insert(word); } while(scanf("%s",word)!=EOF) { printf("%d\n",Trie_search(word)); } return 0; }
数组代码
//自行理解一下 #include <bits/stdc++.h> using namespace std; const int maxn=1e6+5; int trie[maxn][26],num[maxn],cnt=1; void Trie_insert(char word[]) { int n=0; for(int i=0;word[i];i++) { if(trie [word[i]-'a']==0) trie [word[i]-'a']=cnt++; n = trie [word[i]-'a']; num ++; } } int Trie_search(char word[]) { int n=0; for(int i=0;word[i];i++) { if(trie [word[i]-'a']==0) return 0; n = trie [word[i]-'a']; } return num ; } int main() { char word[11]; while(gets(word)) { if(word[0]==NULL) break; Trie_insert(word); } while(scanf("%s",word)!=EOF) { printf("%d\n",Trie_search(word)); } return 0; }
相关文章推荐
- C++——字典树(Trie树)模板——统计难题(HDU1251)
- trie树学习总结(字典树模板)
- 第十二章Trie树(字典树)解决HDU1251
- [复习][HDU1251]字典树(trie树)统计难题
- hdu1251 、1671、1247 字典树,,Trie树
- Trie树|字典树的简介及实现
- Trie树(字典树)
- 字典树(trie树)
- poj 3630 Phone List trie树—字典树 静态数组版!!!
- Trie树|字典树的简介
- Trie树/字典树
- poj 1056 IMMEDIATE DECODABILITY trie树 ——字典树 静态数组版
- Trie树|字典树的简介及实现
- 字典树(Trie树)的C程序实现代码
- poj Shortest Prefixes ——trie树、字典树,基础!!
- HDU 1671 Phone list 字典树(Trie树)
- Trie树|字典树的简介及实现
- 09-08 HDU_Steps5.2 字典树,拓扑,哈夫曼 HDU1075 HDU1251 HDU1671 HDU1285 HDU2094 HDU3231 HDU1053 HDU2527
- HDU 1247 Hat’s Words 字典树(Trie树)
- Trie树|字典树的简介及实现