字典树

字典树Trie Tree

守給你的承諾、 提交于 2019-12-23 00:41:28
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 应用 串的快速检索 给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。 串的排序 给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出。用字典树进行排序,采用数组的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可。 最长公共前缀 对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为当时公共祖先问题。 字典树通常用next指针数组指向子结点,构造整棵树;但是在比赛中为了避免使用指针出错可以使用数组模拟指针的存储方式。 结点的结构体: struct trie{ int next[maxn];//maxn = 字符种类的个数 int v;//记录该字符出现次数 }t[maxm];//maxm = 结点个数 插入的过程就是建树的过程,如果当前当前前缀的子结点中已经出现此时读到的字符,将前缀移动到该子结点,并将这一前缀出现的次数加一;反之

字典树

假如想象 提交于 2019-12-20 13:02:47
字符串集合常用字典树存储,这是一种字符串上的树形数据结构。字典树中每条边都对应一个字,从根节点往下的路径构成一个个字符串。字典树并不直接在节点上存储字符串,而是将词语视作根节点到某节点之间的一条路径,并在终点节点上做个标记“该节点对应词语的结尾”。字符串就是一条路径,要查询一个单词,只需要顺着这条路径从根节点往下走。如果能走到特殊标记的节点,则说明该字符串在集合中,否则说明不存在。 字典树的节点实现 class Node ( object ) : def __init__ ( self , value ) - > None : self . _children = { } self . _value = value def _add_child ( self , char , value , overwrite = False ) : child = self . _children . get ( char ) if child is None : child = Node ( value ) self . _children [ char ] = child elif overwrite : child . _value = value return child 字典树增删改查实现 “增删改查都是查” class Node ( object ) : def __init__ (

ZYB loves Xor I HDU - 5269 字典树

不羁岁月 提交于 2019-12-07 13:28:26
题意: T组样例,给你n个数。你要找出来这n个数中任意两个数的二进制位中 最低位不同 的位置(假设是k),然后让所有2^k加起来就是结果 什么意思? 例如4 和 2 4的二进制是(100),2的二进制是(010),那么它们二进制位中 最低位不同 的位置 就是1,然后把这个2^1加入最后结果就完了 注意:4和2算一次结果,2和4也要算一次结果 解释个样例: 5 4 0 2 7 0 sum=0 4和0:k=2,sum+=2^2 4和2:k=1,sum+=2^1 4和7:k=0,sum+=2^0 4和0:k=2,sum+=2^2 0和2:k=1,sum+=2^1 0和7:k=0,sum+=2^0 0和0:因为0^0=0,题目上lowbit(0)=0,所以sum+=0 2和7:k=0,sum+=2^0 2和0:k=1,sum+=2^1 7和0:k=0,sum+=2^0 sum=4+2+1+4+2+1+0+1+2+1=18 又因为“4和2算一次结果,2和4也要算一次结果”,所以sum*=2 sum=36 题解: 观察发现对于任意一个数 x 来说,只要前 i-1 位和其它数相等,第i位不相等。那么 ans += cnt * pow(2, i-1); cnt 为和它前i-1个前缀都相等的数的个数。 可以利用字典树边插入边更新ans,最后ans*2就是答案。 数组开小了TLE了半天。。。。 代码:

Intelligent IME HDU - 4287 字典树

回眸只為那壹抹淺笑 提交于 2019-12-07 12:57:25
题意: 给你m个字符串,每一个字符对应一个数字,如下: 2 : a, b, c 3 : d, e, f 4 : g, h, i 5 : j, k, l 6 : m, n, o 7 : p, q, r, s 8 : t, u, v 9 : w, x, y, z 输入n个数字串,问这个数字串可以对应几个字符串 比如ade这个字符串对应的数字串就是233 题解: 用这m个字符串建立一颗字典树,对于每一个节点维护一个变量val,他就代表(从树根到这个节点这一个数字串)有多少个对应的字符串 每次插入的时候记录一下最大值就完了 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 using namespace std; 7 typedef struct Trie* TrieNode; 8 char s[130]; 9 char v[5005][10]; 10 struct Trie 11 { 12 int val; 13 TrieNode next[8]; 14 Trie() 15 { 16 val = 0; 17 memset(next,NULL,sizeof(next)); 18 } 19 }; 20 21 void

字典树 && 例题 Xor Sum HDU - 4825 (板子)

岁酱吖の 提交于 2019-12-07 12:50:26
一、字典树描述: Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计 和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大 限度地减少无谓的字符串比较,查询效率比哈希表高。 Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。 它有3个基本性质: 1、根节点不包含字符,除根节点外每一个节点都只包含一个字符。 2、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。 3、每个节点的所有子节点包含的字符都不相同。 二、字典树时间复杂度: 问题: 有一个存放英文单词的文本文件,现在需要知道某些给定的单词是否在该文件中存在,若存在,它又出现了多少次? (暴力方法就不说了) 解法一: 如果将所有的单词都存放在一个map中,每次查找的时间复杂度则降为O(log(n))。 解法二: 假设所有字符串长度之和为n,构建字典树的时间复杂度为O(n)。假设要查找的字符串长度为k,查找的时间复杂度为: O(k)(也相当于O(1))。 三、字典树构建: 举个在网上流传颇广的例子,如下: 题目:给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位置。 分析:这题当然可以用hash来解决

字典树(Trie)详解

狂风中的少年 提交于 2019-12-06 08:35:36
详解字典树(Trie) 本篇随笔简单讲解一下信息学奥林匹克竞赛中的较为常用的数据结构——字典树。字典树也叫Trie树、前缀树。顾名思义,它是一种针对字符串进行维护的数据结构。并且,它的用途超级广泛。建议大家熟练掌握。 字典树的概念 字典树,顾名思义,是关于“字典”的一棵树。即:它是对于字典的一种存储方式(所以是一种数据结构而不是算法)。这个词典中的每个“单词”就是从根节点出发一直到某一个目标节点的路径,路径中每条边的字母连起来就是一个单词。 上图理解: (标橙色的节点是“目标节点“,即根节点到这个目标节点的路径上的所有字母构成了一个单词。) 从这张图我们可以看出,字典树就是一棵树(emm...有些废话的嫌疑),只不过,这棵树的每条边上都有一个字母,然后这棵树的一些节点被指定成了标记节点(目标节点)而已。 这就是字典树的概念。结合上面说的概念,上图所示的字典树包括的单词分别为: a abc bac bbc ca 字典树的功能 根据字典树的概念,我们可以发现:字典树的本质是把很多字符串拆成单个字符的形式,以树的方式存储起来。所以我们说字典树维护的是”字典“。那么根据这个最基本的性质,我们可以由此延伸出字典树的很多妙用。简单总结起来大体如下: 1、维护字符串集合(即 字典 )。 2、向字符串集合中插入字符串(即 建树 )。 3、查询字符串集合中是否有某个字符串(即 查询 )。 4

数据结构 -- Trie字典树

江枫思渺然 提交于 2019-12-05 02:27:27
简介    字典树 :又称单词查找树, Trie树 ,是一种 树形结构 ,是一种哈希树的变种。    优点 : 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。    性质 : 1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符;       2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;       3. 每个节点的所有子节点包含的字符都不相同。    应用场景 :用于 统计,排序 和 保存 大量的 字符串 (但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。        代码 实现 本文使用链表来实现Trie字典树,字符串的每个字符作为一个Node节点,Node主要有两部分组成: 是否是单词 (boolean isWord) 节点所有的子节点,用map来保存 (Map next) 添加 public void add(String word) { Node current = root; char[] cs = word.toCharArray(); for (char c : cs) { Node next = current.next.get(c); if (next == null) { //一个字符对应一个Node节点 current.next.put(c, new Node())

hdu1247-Hat’s Words-(字典树)

被刻印的时光 ゝ 提交于 2019-12-04 18:12:22
http://acm.hdu.edu.cn/showproblem.php?pid=1247 题意:给出一堆单词,求哪些单词是其中某两个单词拼接起来的。 题解:用字典树存储所有的单词,标记结束点,再次遍历单词的时候如果遍历过程遇到结束点则表明有单词是该单词的前缀,查找后半段字母(后缀)看看最后能不能遇到结束点,如果遇到了则该单词是某两个单词的前后缀,可以输出。详看注释。 #include<stdio.h> #include<iostream> #include<algorithm> #include<cstring> #include<math.h> #include<string> #include<map> #include<queue> #include<stack> #include<set> #include<ctime> #define ll long long #define inf 0x3f3f3f3f const double pi=3.1415926; using namespace std; int maxx=50005; typedef struct node { int flag;///判断是否单词在这里就完了,作为前缀 node *next[27]; }; node* root=new node();///根节点始终为空 void insert(char

POJ3630-Phone List-(字典树)

▼魔方 西西 提交于 2019-12-04 15:20:53
一直没有学字典树,听起来很唬人,闲来无事找一道入门题做做。 字典树:又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 它有3个基本性质: 根节点不包含字符,除根节点外每一个节点都只包含一个字符; 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; 每个节点的所有子节点包含的字符都不相同。 搜索字典项目的方法为: (1) 从根结点开始一次搜索; (2) 取得要查找关键词的第一个字母, 并根据该字母选择对应的子树并转到该子树继续进行检索 ; (3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。 (4) 迭代过程…… (5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。 用一张图表示会比较直观,至于实现过程就是编码能力的问题了。 http://poj.org/problem?id=3630 题意:给出好多不超过10位的电话号码,如果存在某一个电话号码(如911)是其他电话号码(91110086)的前缀就会导致后者无法拨通,问是否全部电话号码都能拨通。 思路:开一个tree[maxx]

hdoj1247(字典树)

此生再无相见时 提交于 2019-12-04 04:12:15
题目链接:https://vjudge.net/problem/HDU-1247 题意:给定n个字符串(n<=50000),判断其中哪些字符串恰能由另外两个不同的字符串连接而成。 思路:   暴力字典树即可。右n个字符串建树,然后把每个字符串拆分判断两部分是否都在树中。 AC code: #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=50005; const int maxm=1e6+5; int n,trie[maxm][30],key[maxm],cnt; char str[maxn][30]; void insert(char *s){ int len=strlen(s),u=0; for(int i=0;i<len;++i){ int t=s[i]-'a'; if(!trie[u][t]){ ++cnt; memset(trie[cnt],0,sizeof(trie[cnt])); key[cnt]=0; trie[u][t]=cnt; } u=trie[u][t]; if(i==len-1) key[u]=1; } } bool query(int k,int l,int r){ int u=0; for(int i=l;i<=r;++i