Trie树介绍及应用 POJ3630
Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
它有3个基本性质:
1.根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3.每个节点的所有子节点包含的字符都不相同。
典型应用:
1.已知n个由小写字母构成的平均长度为10的单词,判断其中是否存在某个串为另一个串的前缀子串
2. 即时响应用户输入的AJAX搜索框.(本质上,Trie是一颗存储多个字符串的树。相邻节点间的边代表一个字符,这样树的每条分支代表一则子串,而树的叶节点则代表完整的字符串。和普通树不同的地方是,相同的字符串前缀共享同一条分支。)
3、有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
9、1000万字符串,其中有些是重复的,需要把重复的全部去掉,保留没有重复的字符串。请怎么设计和实现?
10、 一个文本文件,大约有一万行,每行一个词,要求统计出其中最频繁出现的前10个词,请给出思想,给出时间复杂度分析。
13、寻找热门查询:搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。假设目前有一千万个记录,这些查询串的重复读比较高,虽然总数是1千万,但是如果去除重复和,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就越热门。请你统计最热门的10个查询串,要求使用的内存不能超过1G。
/* POJ 3630 Trie树
题意:求给定的多个串中是否存在,某个串是另一个串的前缀。
解题思路:在每次插入一个串的同时判断。对于该问题,只存在以下两种情况:
1.当前插入的串的前缀是前面的某个串
2.当前插入的串是前面某个串的前缀。把插入串的最后一个节点单独拿出来判断,如果该串的最后一个节点已经被分配过地址,则说明这种情况成立。
*/
实例代码:
1 #include <stdio.h> 2 struct Node{ 3 Node * child[MAX]; 4 bool strEnd; 5 Node():strEnd(false){ 6 for (int j = 0; j < MAX; ++j)child[j] = NULL; 7 } 8 }nodePool[400005], *pNode; 9 int poolIndex, n, t; 10 bool insertNode(Node *root, char *s){ 11 int i; 12 pNode = root; 13 for (i = 0; s[i + 1]; ++i){ //因为最后一个字符结点要添加结束符,所以s[i+1] 14 if (pNode->child[s[i] - '0'] == NULL){ 15 pNode->child[s[i] - '0'] = root + ++poolIndex; 16 } 17 pNode = pNode->child[s[i] - '0']; 18 if (pNode->strEnd) return false; 19 } 20 bool ok; 21 if (pNode->child[s[i] - '0'] == NULL){ 22 pNode->child[s[i] - '0'] = root + ++poolIndex; 23 ok = true; 24 } 25 else ok = false; //现字符串是之前字符串的前缀 26 pNode = pNode->child[s[i] - '0']; 27 pNode->strEnd = true; 28 return ok; 29 } 30 int main(){ 31 while (t--){ 32 scanf("%d", &n); 33 bool isDup = false; 34 poolIndex = 0; 35 for (int i = 0; i < n; i++){ 36 scanf(" %s", str); 37 if ((!isDup) && (!insertNode(nodePool, str))){ 38 isDup = true; 39 } 40 } 41 if (isDup) printf("NO\n"); 42 else printf("YES\n"); 43 for (int i = 0; i <= poolIndex; ++i){ 44 pNode = &nodePool[i]; 45 for (int j = 0; j < MAX; ++j)pNode->child[j] = NULL; 46 pNode->strEnd = false; 47 } 48 } 49 return 0; 50 }