字典树(转)

字典树:很强大的数据结构,实现多个字符串的查找、对其个数的纪录以及对其子串的查询。

连接:http://blog.csdn.net/chenzhenyu123456/article/details/46490539

这里讲下建树过程:

准备:MAX 记录总节点数目

[cpp] view plaincopy

  1. char str[1010][50];//输入的字符串集
  2. int ch[MAX][30];//字典树的实现
  3. int word[MAX];//记录当前节点下有多少个单词
  4. int val[MAX];//标记单词节点
  5. int sz;//节点数

初始化:

[cpp] view plaincopy

  1. void init()
  2. {
  3. sz = 1;
  4. memset(ch[0], 0, sizeof(ch[0]));
  5. memset(word, 0, sizeof(word));
  6. }

返回字符的ascll码值:

[cpp] view plaincopy

  1. int idx(char x)
  2. {
  3. return x - ‘a‘;
  4. }

插入字符串:

[cpp] view plaincopy

  1. void insert(char *s)
  2. {
  3. int i, j, len = strlen(s);
  4. int u = 0;//根节点开始
  5. for(i = 0; i < len; i++)
  6. {
  7. int c = idx(s[i]);
  8. if(!ch[u][c])//当前节点不存在
  9. {
  10. memset(ch[sz], 0, sizeof(ch[sz]));//初始化新节点
  11. val[sz] = 0;
  12. ch[u][c] = sz++; //节点数增一
  13. }
  14. u = ch[u][c];
  15. word[u]++;//单词数加一
  16. }
  17. val[u] = 1;//标记单词节点
  18. }

查找以字符串s为前缀的字符串 在字符串集中有多少个

[cpp] view plaincopy

  1. int findnum(char *s)//查询以该s为前缀的字符串有多少个
  2. {
  3. int i, j, l = strlen(s);
  4. int u = 0;
  5. for(i = 0; i < l; i++)
  6. {
  7. int c = idx(s[i]);
  8. if(!ch[u][c]) return 0;//不存在
  9. u = ch[u][c];
  10. }
  11. return word[u];
  12. }

查找并输出字符串在串集里面唯一确定的最短前缀 :

[cpp] view plaincopy

  1. void findprefix(char *s)
  2. {
  3. int i, j, len = strlen(s);
  4. int u = 0;
  5. for(i = 0; i < len; i++)
  6. {
  7. int c = idx(s[i]);
  8. u = ch[u][c];//继续查找
  9. printf("%c", s[i]);
  10. if(word[u] == 1)//节点下只有一个单词
  11. return ;
  12. }
  13. }

判断该字符串是不是串集里某个字符串前缀 :

[cpp] view plaincopy

  1. bool judgeprefix(char *s)
  2. {
  3. int i, j, len = strlen(s);
  4. int u = 0;
  5. for(i = 0; i < len; i++)
  6. {
  7. int c = idx(s[i]);
  8. u = ch[u][c];//继续查找
  9. if(word[u] == 1)//不是任何字符串的前缀
  10. return true;
  11. }
  12. return false;//是前缀
  13. }

判断字符串是否由串集里的两个字符串构成: 假设该字符串分s1,s2两部分,这里只实现s1的查找

[cpp] view plaincopy

  1. bool finds(char *s)
  2. {
  3. int i, j, len = strlen(s);
  4. int u = 0;
  5. for(i = 0; i < len; i++)
  6. {
  7. int c = idx(s[i]);
  8. if(!ch[u][c])//不存在节点
  9. return false;
  10. u = ch[u][c];
  11. }
  12. return val[u];//最后一个是不是单词节点
  13. }

大模板:

[cpp] view plaincopy

  1. #include <cstdio>
  2. #include <cstring>
  3. #define MAX 50000+10
  4. using namespace std;
  5. char str[1010][50];//输入的字符串集
  6. int ch[MAX][30];//字典树的实现
  7. int word[MAX];//记录当前节点下有多少个单词
  8. int val[MAX];//标记单词节点
  9. int sz;//节点数
  10. int idx(char x)
  11. {
  12. return x - ‘a‘;
  13. }
  14. void init()
  15. {
  16. sz = 1;
  17. memset(ch[0], 0, sizeof(ch[0]));
  18. memset(word, 0, sizeof(word));
  19. }
  20. void insert(char *s)
  21. {
  22. int i, j, len = strlen(s);
  23. int u = 0;//根节点开始
  24. for(i = 0; i < len; i++)
  25. {
  26. int c = idx(s[i]);
  27. if(!ch[u][c])//当前节点不存在
  28. {
  29. memset(ch[sz], 0, sizeof(ch[sz]));//初始化新节点
  30. val[sz] = 0;
  31. ch[u][c] = sz++; //节点数增一
  32. }
  33. u = ch[u][c];
  34. word[u]++;//单词数加一
  35. }
  36. val[u] = 1;//标记单词节点
  37. }
  38. //查找以字符串s为前缀的字符串 在字符串集中有多少个
  39. int findnum(char *s)//查询以该s为前缀的字符串有多少个
  40. {
  41. int i, j, l = strlen(s);
  42. int u = 0;
  43. for(i = 0; i < l; i++)
  44. {
  45. int c = idx(s[i]);
  46. if(!ch[u][c]) return 0;//不存在
  47. u = ch[u][c];
  48. }
  49. return word[u];
  50. }
  51. //查找并输出字符串在串集里面唯一确定的最短前缀
  52. void findprefix(char *s)
  53. {
  54. int i, j, len = strlen(s);
  55. int u = 0;
  56. for(i = 0; i < len; i++)
  57. {
  58. int c = idx(s[i]);
  59. u = ch[u][c];//继续查找
  60. printf("%c", s[i]);
  61. if(word[u] == 1)//节点下只有一个单词
  62. return ;
  63. }
  64. }
  65. //判断该字符串是不是串集里某个字符串前缀
  66. bool judgeprefix(char *s)
  67. {
  68. int i, j, len = strlen(s);
  69. int u = 0;
  70. for(i = 0; i < len; i++)
  71. {
  72. int c = idx(s[i]);
  73. u = ch[u][c];//继续查找
  74. if(word[u] == 1)//不是任何字符串的前缀
  75. return true;
  76. }
  77. return false;//是前缀
  78. }
  79. //判断字符串是否由串集里的两个字符串构成:假设该字符串分两部分,这里只实现一部分的查找
  80. bool finds(char *s)
  81. {
  82. int i, j, len = strlen(s);
  83. int u = 0;
  84. for(i = 0; i < len; i++)
  85. {
  86. int c = idx(s[i]);
  87. if(!ch[u][c])//不存在节点
  88. return false;
  89. u = ch[u][c];
  90. }
  91. return val[u];//最后一个是不是单词节点
  92. }
时间: 2024-10-11 10:09:54

字典树(转)的相关文章

hdu 1251 统计难题(字典树)

Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input 输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串. 注意:本题只有一组测试数据,处理到文件结束. Output 对于每个提

51nod round3# 序列分解(折半枚举+字典树)

小刀和大刀是双胞胎兄弟.今天他们玩一个有意思的游戏. 大刀给小刀准备了一个长度为n的整数序列.小刀试着把这个序列分解成两个长度为n/2的子序列. 这两个子序列必须满足以下两个条件: 1.他们不能相互重叠. 2.他们要完全一样. 如果小刀可以分解成功,大刀会给小刀一些糖果. 然而这个问题对于小刀来说太难了.他想请你来帮忙. Input 第一行给出一个T,表示T组数据.(1<=T<=5) 接下来每一组数据,输入共2行. 第一行包含一个整数n (2<=n<=40且为偶数). 第二行给出n

白话算法与数据结构之【字典树】

1. 什么是trie树 1.Trie树 (特例结构树) Trie树,又称单词查找树.字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高.      Trie的核心思想是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. Trie树也有它的缺点,Trie树的内存消耗非常大.当然,或许用左儿子

[算法系列之二十]字典树(Trie)

一 概述 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 二 优点 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高. 三 性质 (1)根节点不包含字符,除根节点外每一个节点都只包含一个字符: (2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串: (3)每个节点的所有子节点包含的字符都不相同. 单词列表为"apps&

poj 3764 The xor-longest Path(字典树)

题目链接:poj 3764 The xor-longest Path 题目大意:给定一棵树,每条边上有一个权值,找出一条路径,使得路径上权值的亦或和最大. 解题思路:dfs一遍,预处理出每个节点到根节点路径的亦或和rec,那么任意路径均可以表示rec[a] ^ rec[b],所以问题 就转换成在一些数中选出两个数亦或和最大,那么就建立字典树查询即可. #include <cstdio> #include <cstring> #include <algorithm> us

字典树

字典树(Trie)是一种很特别的树状信息检索数据结构,如同其名,它的构成就像一本字典,可以让你快速的进行字符插入.字符串搜索等. Trie 一词来自 retrieval,发音为 /tri:/ "tree",也有人读为 /tra?/ "try". 字典树设计的核心思想是空间换时间,所以数据结构本身比较消耗空间.但它利用了字符串的共同前缀(Common Prefix)作为存储依据,以此来节省存储空间,并加速搜索时间.Trie 的字符串搜索时间复杂度为 O(m),m 为最

字典树的简单实现

Trie树,又称为字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树数据结构. 用于保存大量的字符串.它的优点是:利用字符串的公共前缀来节约存储空间. Trie的核心思想是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. 它有3个基本性质: 1.根节点不包含字符,除根节点外每一个节点都只包含一个字符. 2.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串. 3.每个节点的所有子节点包含的字符都不相同. 搜索字典项目的方法为: (1)

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

uva 1385 - Billing Tables(字典树)

题目链接:uva 1385 - Billing Tables 题目大意:给定n个电话前缀,每个前缀是一个区域的前缀,现在要生成一个新的电话单,即对于每个电话号码,从旧的电话单上从前向后遍历,如果出现前缀匹配,则该电话号码对应的即为当前的区号,要求生成的新电话单尽量小. 解题思路:用dfs建立字典树,在区间范围内的点对应均为对应的区号,注意如果70.71.72....79都为SB的话,那么可以合并成7,并且对应区号为SB. 注意合并的条件为区号相同即可,并不是说对应旧电话单匹配位置相同. 注意这组

trie树(字典树)

1. trie树,又名字典树,顾名思义,它是可以用来作字符串查找的数据结构,它的查找效率比散列表还要高. trie树的建树: 比如有字符串"ab" ,"adb","adc"   可以建立字典树如图: 树的根节点head不存储信息,它有26个next指针,分别对应着字符a,b,c等.插入字符串ab时,next['a'-'a']即next[0]为空,这是申请一个结点放在next[0]的位置,插入字符串db时,next['d'-'a']即next[3]