字典树

【01字典树】hdu-5536 Chip Factory

只谈情不闲聊 提交于 2019-11-27 14:09:08
【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5536 【题意】 求一个式子,给出一组数,其中拿出ai,aj,ak三个数,使得Max{ (ai+aj) ^ ak } 【题解】 其实这里就需要大家做一个删除的操作; 类似于dfs的恢复现场的操作即可。 【代码】 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N = 1e5+10; 6 int Son[N*31][2]; 7 int a[N],idx; 8 int Cnt[N*31]; 9 void Insert( int x ){ 10 int p = 0 ; 11 for(int i=30;~i;i--){ 12 int t = x >> i & 1 ; 13 if( !Son[p][t] ){ 14 Son[p][t] = ++idx; 15 } 16 p = Son[p][t]; 17 Cnt[p] ++ ; 18 } 19 } 20 void Delete( int x ){ 21 int p = 0 , tmp ; 22 for(int i=30;~i;i--){ 23 int t = x >> i & 1 ; 24 if(

Python实现字典树

笑着哭i 提交于 2019-11-27 12:44:09
字典树,又称单词查找树,Trie 树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 注:定义来自百度百科。 字典树的主要性质 它有 3 个基本性质: 根节点不包含字符,除根节点外每一个节点都只包含一个字符; 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; 每个节点的所有子节点包含的字符都不相同。 基本功能介绍 在接下来的内容里,我们将逐步介绍字典树的具体功能是如何实现的。 1. 创建 TrieNode 类 创建一个 TrieNode 的类,构建内置字典结构 具体实现代码如下 class TrieNode: def __init__(self): self.nodes = dict() # 构建字典 self.is_leaf = False 2. 添加 insert 函数 插入一个字到字典树中 具体实现代码如下: def insert(self, word: str): curr = self for char in word: if char not in curr.nodes: curr.nodes[char] = TrieNode() curr = curr

Trie 字典树

不羁的心 提交于 2019-11-27 11:07:27
Trie Trie(字典树)是一种用于实现字符串快速检索的多叉树结构。Tire的每个节点都有若干个字符指针,若再插入和检索字符串时扫描到一个字符,就沿字符走向指向的节点。 插入 当需要插入一个字符串时,我们从根走起,依次扫描每一个字符: 若字符指向一个已经存在的节点,则顺着节点继续走下去 若字符指向空,则新建一个节点,继续走下去。 当字符串中的字符都检索完毕时,记录下其终点结点。 检索 当需要检索一个字符串是否存在时,我们从根走起,一次扫描每一个字符: 若字符指向空,则说明不存在,结束。 若字符指向一个结点,则继续走下去。 当字符串中所有字符被检索完毕时,若当前结点是一个被标记为终点的节点,说明字符串存在,否则说明其不存在。 1 int trie[SIZE][26], tot = 1; 2 void insert(char* str){ 3 int len = strlen(str), p = 1; 4 for (int k = 0; k < len; k++){ 5 int ch = str[k] - 'a'; 6 if (trie[p][ch] == 0) trie[p][ch] = ++tot; 7 p = trie[p][ch]; 8 } 9 end[p] = true; 10 } 11 bool search(char* str){ 12 int len = strlen

字典树入门及例题展示,弄懂即便入门

陌路散爱 提交于 2019-11-27 04:54:34
博主写的非常给力,我觉得比较通俗易懂,所以冒昧转载,也希望更多的朋友能够轻松弄懂字典树。 每个字符有很多个分支,打黄色标记的就是字符串的结尾,所以这颗字典树中有哪些字符串呢,“ab”,“ay”,“ayf”,“c”,“cc”,“cd”,其他的枝没有画全。 顺序存储字符串:“ab”“ay”“ayf”“c”“cc”“cd”……(节点编号讲究先到先得) 数组tree[i][j]:代表i节点的第j个儿子的根编号。(获取第几个孩子可以s[i]-‘a’,以图中5节点举例,就是tree[0][2]=5) 数组flag[i]:为true代表到该节点为一个字符串 # include <bits/stdc++.h> using namespace std ; const int maxn = 2e6 + 5 ; int tree [ maxn ] [ 30 ] , tot = 0 ; bool flag [ maxn ] ; void add ( char * s ) { int root = 0 , id , len = strlen ( s ) ; for ( int i = 0 ; i < len ; ++ i ) { id = s [ i ] - 'a' ; if ( ! tree [ root ] [ id ] ) tree [ root ] [ id ] = ++ tot ; root =

字典树

一世执手 提交于 2019-11-27 04:43:40
字典树概念 是一种树形结构 Trie树的基本性质可以归纳为: (1) 根节点不包括字符,除根节点意外每个节点只包含一个字符 (2) 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串 (3) 每个节点的所有子节点包含的字符串不相同 当然,Trie树也有一个缺点,如果系统中存在大量字符串且这些字符串基本没有公共前缀,则相应的trie树将非常消耗内存 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 基本操作有:查找插入删除 应用 字符串检索 字符串公共前缀 排序 后缀树,AC自动机 字典树的储存:利用二维数组 如果用一位数组表示,时26^n空间复杂度,如果用二维数组表示,是26*n的空间复杂度,查询时间复杂度为O(1); 对于单个字符tree[root][id];root 表示这个字母在单词的第几项,id表示这个字母的在字母表里的下标 如对于acb 1000 0020 0300 数字表示顺序 对于 1000 0234 0000 表示 ab ac ad sum[1]=3 sum[2]=1; sum[3]=1; sum[4]=1; 如果前缀都是一样的话没有问题,但前缀不一样时 对于 ac cb 103 002 000 040 原来3应该在i=2这一行的j=2,但cb是一个新的数,所以c在第一行 总结 tree[i][j]=z

CodeFoeces GYM 101466A Gaby And Addition (字典树)

筅森魡賤 提交于 2019-11-27 03:59:23
gym 101466A Gaby And Addition 题目分析 题意: 给出n个数,找任意两个数 “相加”,求这个结果的最大值和最小值,注意此处的加法为不进位加法。 思路: 由于给出的数最多有 1e6 个,且每个数的值最大为 1e18 ,又因为特殊的加法运算,我们自然无法用常规的方法解决 注意到这个加法运算可以分配到每一位上进行运算,而且最大为1e18,十九位数,那么我们就可以用字典树来存储每个数,并进行计算,为了将字典树每个结点的深度和数的位数对应起来,我们可以将每个数都处理为19位数,从高位依次存入字典树,这样一来,就方便我们求最值了。 然后就是求最值的问题,我最初的想法是先将所有数存入字典树,随后枚举字典树的每条链(从根结点到叶子节点的路径),以求出最值,不过TLE了,想来这样写确实时间比较长,最坏的情况下查询用时:5 ^ 18 次,大约3.8e13次运算, 妥妥地TLE。不过我们可以在插入某个数之前,求出这个数和字典树中存在的数“相加”的得到的最值,随后将这个数存入字典树,最后所有数存入字典树后,就可以得到最值了。 总结: 这个题目写了我近半天,确定是字典树后,由于求最值这里对原方法用时估计错误,导致自己一直TLE在第四组样例,后来请教同学才发现问题。 还有就是这个地方求最值的时候不要用递归,在这里递归的效率很低。 代码区 #include<iostream>

字典树

无人久伴 提交于 2019-11-27 00:50:08
HDU 1251 代码 #include < iostream > using namespace std; const int kind = 26 ; // 字母种类 struct Treenode // 树的结点结构 { int count; // 这个附加变量在本题中记录遍历到该结点形成的字符串出现的次数,在不同题中可记录不同的内容。 Treenode * next[kind]; // 指向儿子结点 Treenode() // 每个结点的初始化 { count = 1 ; for ( int i = 0 ;i < kind;i ++ ) next[i] = NULL; } }; void insert(Treenode *& root, char * word) // 向以root为根结点的树中插入串word { Treenode * location = root; int i = 0 ,branch = 0 ; if (location == NULL) {location = new Treenode();root = location;} while (word[i]) { branch = word[i] - ' a ' ; if (location -> next[branch]) location -> next[branch] -> count ++ ; //

HDU 1671 Phone List(字典树)

旧城冷巷雨未停 提交于 2019-11-26 16:00:58
- HDU 1671 - Phone List Time Limit: 3000/1000 MS (Java/Others) | Memory Limit: 32768/32768 K (Java/Others) 题意: 给定一个整数 t ,表示测试案例数,每个测试案例给定一个整数 n ,接下来输入 n 行号码,判断这些号码中是否有某个号码是另一个号码的前缀,若有,则输出‘NO’,否则,输出’YES’。 数据范围: 1 <= t <= 40, 1 <= n <= 10000. 解题思路: 字典树 本题用字典树的常规做法即可解出,但有一点要注意,那就是 后来输入的号码可能是前面某个号码的前缀 ,所以在用字典树来解题之前,要先给每组的 所有号码按长短排一下序 ,短的在前,长的在后,这样就能保证后面判断的号码不可能是前面已判断的号码的前缀。 代码: # include <iostream> # include <cstdio> # include <cstring> # include <string> # include <algorithm> # include <cmath> # include <stack> # include <queue> # include <vector> # include <map> using namespace std ; # define

字典树模板

▼魔方 西西 提交于 2019-11-26 10:30:01
字典树(trie树)是一种根据字符串前缀在log(n)左右时间内完成查询的数据结构。 插入 这里可能需要节点数统计或者单词数统计 # include <bits/stdc++.h> # include <tr1/unordered_map> # define fi first # define se second # define show(a) cout<<a<<endl; # define show2(a,b) cout<<a<<" "<<b<<endl; # define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl; using namespace std ; typedef long long ll ; typedef pair < int , int > P ; typedef pair < P , int > LP ; const ll inf = 0x3f3f3f3f ; const int N = 1e6 + 10 ; const ll mod = 10007 ; const int base = 131 ; tr1 : : unordered_map < ll , ll > mp ; ll n , m , id , x , y , k , q ; ll num [ N ] ; //单词出现次数 或者 编号 ll tree

Trie Tree字典树(讲解+模板)

偶尔善良 提交于 2019-11-25 19:42:24
一、引入 字典是干啥的?查找字的。 字典树自然也是起查找作用的。查找的是啥?单词。 看以下几个题: 1、给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单词表中出现过。 答:简单!map,短小精悍。 好。下一个 2、给出n个单词和m个询问,每次询问一个前缀,回答询问是多少个单词的前缀。 答:map,把每个单词拆开。 judge:n<=200000,TLE! 这就需要一种高级数据结构——Trie树(字典树) 二、原理 在本篇文章中,假设所有单词都只由小写字母构成 对cat,cash,app,apple,aply,ok 建一颗字典树,建成之后如下图所示 由此可以看出: 1、字典树用边表示字母 2、有相同前缀的单词公用前缀节点,那我们可以的得出每个节点最多有26个子节点(在单词只包含小写字母的情况下) 3、整棵树的根节点是空的。为什么呢?便于插入和查找,这将会在后面解释。 4、每个单词结束的时候用一个特殊字符表示,图中用的‘′,那么从根节点到任意一个‘′,那么从根节点到任意一个‘’所经过的边的所有字母表示一个单词。 三、基本操作 A、insert,插入一个单词 1.思路 从图中可以直观看出,从左到右扫这个单词,如果字母在相应根节点下没有出现过,就插入这个字母;否则沿着字典树往下走,看单词的下一个字母。 这就产生一个问题:往哪儿插?计算机不会自己选择位置插