字典树

字典树-208. 实现 Trie (前缀树)-PYTHON

假装没事ソ 提交于 2020-02-17 14:42:17
python利用字典结构的简便版本(注意看注释理解) class Trie : def __init__ ( self ) : """ Initialize your data structure here. """ self . lookup = { } #构建一个字典结构,用于存储元素数据 def insert ( self , word ) : """ Inserts a word into the trie. """ tree = self . lookup #给公共字典取别名 for a in word : if a not in tree : tree [ a ] = { } #逐元素提取字母到字典中查找是否存在,如果不存在就在字典内建立一个空的子字典 tree = tree [ a ] #跟踪标记位置变换,进入到字字典中进行操作 # 单词结束标志 tree [ "#" ] = "#" #插入单词结束在最后一个字字典中插入结束符 print ( self . lookup ) def search ( self , word ) : """ Returns if the word is in the trie. """ tree = self . lookup for a in word : if a not in tree : #{u'a': {u'p': {u'p'

字典树(Trie)

时光怂恿深爱的人放手 提交于 2020-02-12 22:56:28
一、基本概念:   字典树(Trie)是一种用于实现字符串快速检索的多叉树结构。字典树的每一个结点都拥有若干个字符指针,若在插入或检索字符串时扫描到一个字符 c,就沿着当前结点的 c 字符指针,走向该指针指向的结点。 1、初始化   一棵空字典树仅包含一个根节点,该点的字符指针均指向空。 2、插入操作   当需要插入一个字符串 str 时,我们另一个指针 p 指向根节点。人后,依次扫描 s 中的每一个字符 c :   (1)若 p 的 c 字符指针指向一个已经存在的结点 q,则令 p = q   若 p 的 c 字符指针指向空,则新建一个结点 q,令 p = q   当 s 中的字符扫描完毕时,在当前结点 p 上标记它是一个字符串的尾部 int trie [ maxn ] [ 26 ] , tot = 1 ; bool nd [ maxn ] ; void _insert ( char str [ ] ) { int p = 1 ; for ( int k = 0 ; str [ k ] ; k ++ ) { int ch = str [ k ] - 'a' ; if ( trie [ p ] [ ch ] == 0 ) trie [ p ] [ ch ] = ++ tot ; p = trie [ p ] [ ch ] ; } nd [ p ] = true ; } 2、检索操作

字典树存在的意义

喜你入骨 提交于 2020-02-10 08:22:01
1. 字典树   曾经遇到这样一个问题:很多单词,这些单词只含小写字母,并且不会有重复的单词出现,现在要统计出以某个字符串为前缀的单词数量,单词本身也是自己的前缀。先看看用常规的方法解决这个问题的复杂度。假设单词表容量为M,需要统计的前缀数量为N,前缀的平均长度是L,则常规算法思路是:对于每个前缀搜索每个单词,看看这个前缀是不是这个单词的前缀,如果是数量+1。这样的话时间复杂度为O(N*M*L),如果N相当大的话,这个算法的复杂度将无法接受啦。其实这就是字典树的典型应用啦。   我们先学习一下字典树,在解决上面的问题。字典树又称trie树,从名字上看很显然是一种树形结构了。字典树有以下几个特点:1.利用串的公共前缀,节约内存;2.根结点不包含任何字母;3.其余结点仅包含一个字母;4.每个结点的子节点包含字母不同。看看一个例子吧:下面就是一个字典树(图片来自百度百科)    上面的树就是一颗典型的字典树了,字典树中存储的单词包括:abc、abcd、abd、b、bcd、efg、hig,即:所有标记为红心的才是单词的结尾字母。对比上面的trie树的特点仔细看一下,理解一下到底什么是字典树。实际上字典树包括常见的两种种操作是:查找和插入操作。我觉得有必要看看字典树的基础代码:( 代码 ) View Code 1 //字典树的每个节点 2 struct node 3 { 4 bool

数据结构-字符串-字典树

吃可爱长大的小学妹 提交于 2020-02-09 01:33:29
数据结构-字符串-字典树 字典树就是著名的 t r i e trie t r i e 树,是未来学很多字符串自动机的必备前置知识。 用处:插入字符串,查找字符串出现次数。 这个数据结构就是一个有根树,根节点编号为 1 1 1 。除了根节点外,每个节点上有一个字母。对于每个节点 x x x , c h [ x ] [ c ] ch[x][c] c h [ x ] [ c ] 表示这个节点的儿子中字符为 c c c 的那个的编号, m k [ x ] mk[x] m k [ x ] 表示插入的字符串中以这个节点为结尾的字符串数。 每当要插入一个字符串 s s s (下标从 1 1 1 开始)时,就从根节点 1 1 1 开始,如果根节点 1 1 1 没有字符为 s [ 1 ] s[1] s [ 1 ] 的子节点,就创造一个那个节点,然后无论那个节点是不是刚被创造出来的,走到那个节点。然后再看那个节点有没有字符为 s [ 2 ] s[2] s [ 2 ] 的子节点,然后如此操作,走到 s [ n ] s[n] s [ n ] (字符串长度为 n n n )时, m k [ mk[ m k [ 单前节点 ] + + ]++ ] + + 。 查找字符串 s s s 时,也从根节点 1 1 1 开始,沿着 c h [ ] [ ] ch[][] c h [ ] [ ] 数组走

字典树基础知识学习笔记

北城余情 提交于 2020-02-08 05:21:10
节点最多有N个时,开一个二维数组son[N][M](M为所有字符的总个数),记录每个点的儿子。对每一个字符串的结尾的序号,用cnt[N] 数组来记录有多少个这样的字符串,这张图可以帮助理解: 假设给定的字符串(只由a, b, c, d组成)为:aabc, aabd, aabd, cdb, cdba son[i][4] 就是第i个节点下面的4个格子 下面附两道模板题: 1. https://www.acwing.com/problem/content/837/ #include <iostream> #include <cstdio> #include <cstring> #define N 100010 using namespace std; int son[N][26], cnt[N], idx; int n; void insert(string str) { int p = 0; // 每次插入都从root节点开始 for (int i = 0; i < str.size(); i ++) { int u = str[i] - 'a'; // 找到属于这个节点的对应的格子 if(!son[p][u]) son[p][u] = ++ idx; // 如果这个格子是空的,就把它标记上序号 p = son[p][u]; // 然后走到这个格子上 } //

POJ - 3630 Phone List (字典树)

|▌冷眼眸甩不掉的悲伤 提交于 2020-02-05 14:11:49
t 组数据,n 个电话号码,如果拨打号码的时候,先拨通了某个号码,那么这一串号码就无法全部拨通, eg:911 和 9112016652 相比 后者就无法被拨通,因为 911 会先被拨通。 如果n 个电话号码都可拨通,输出 YES ,不然输出 NO。 Input 样例数t(1 ≤ t ≤ 40), 每组样例有 n个电话号码 ,(1 ≤ n ≤ 10000). 接下来有n个号码字符串,每个字符串最多10位。 Output 对于每组样例,如果n 个电话号码都可拨通,输出 YES ,不然输出 NO。 Sample Input 2 3 911 97625999 91125426 5 113 12340 123440 12345 98346 Sample Output NO YES #include<cstdio> #include<cstring> using namespace std; const int maxn=1e5+5; char s[maxn][15]; int trie[maxn][15]; bool flag[maxn]; int k; void insert_(char a[]) { int p=0; int len=strlen(a); for(int i=0;i<len;i++) { int c=a[i]-'0'; if(!trie[p][c]) trie[p][c

Phone List(字典树)

房东的猫 提交于 2020-02-05 09:59:08
Phone List Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 25709 Accepted: 7785 Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers: Emergency 911 Alice 97 625 999 Bob 91 12 54 26 In this case, it's not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob's phone number. So this list would not be consistent. Input The first line of input gives a single integer, 1 ≤ t ≤

HDU 1671 Phone List(字典树)

牧云@^-^@ 提交于 2020-02-05 09:55:58
Phone List Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 22697 Accepted Submission(s): 7684 Problem Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let’s say the phone catalogue listed these numbers: 1. Emergency 911 2. Alice 97 625 999 3. Bob 91 12 54 26 In this case, it’s not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob’s phone number. So this list would not be

字典树 前缀树 trie

让人想犯罪 __ 提交于 2020-02-04 18:17:13
这几天在看AC自动机,发现AC自动机有个前置任务:掌握字典树。 字典树的原理其实就是储存并检索字符串的前缀。 实现过程其实就是用一个变量去储存树的下标,如果插入的字符串不停更新下标。 放一道模板题: P2580 于是他错误的点名开始了 AC代码: # include <iostream> # include <cstdio> # include <cmath> # include <string> # include <cstring> # include <algorithm> # include <limits> # include <vector> # include <stack> # include <queue> # include <set> # include <map> using namespace std ; //#pragma GCC optimize(3,"Ofast","inline") # define LL long long # define MT(a,b) memset(a,b,sizeof(a)) const int mod = 1000007 ; const int maxn = 500010 ; const int ONF = - 0x3f3f3f3f ; const int INF = 0x3f3f3f3f ; int tot ,

HDU4825 Xor Sum(01字典树模板题)

夙愿已清 提交于 2020-02-04 00:39:23
题意: 给一个长度为n的序列,m个询问,每次询问给出一个数字x,问数组中哪个元素与x异或的值最大 思路: 1、我们按照长度为32位的二进制01字符串建树,从高位开始建。将所有数据都建到树中。 2、接下来对于每个查询,同样处理成35位二进制01字符串,对应进行查询,如果当前位子是0,那么尽量往1那边走,同理,如果当前位子是1,那么尽量往0那边走即可。 #include<iostream> #include<algorithm> #include<cstring> const int maxn=1e5+10; using namespace std; struct Tire{ int ch[maxn*32][2],val[maxn*32],sz; void init() { sz=0; memset(val,0,sizeof(val)); memset(ch[0],0,sizeof(ch[0])); } void insert(int x) { int u=0; for(int i=31;i>=0;i--){ int tem=(x>>i)&1; if(!ch[u][tem]) ch[u][tem]=++sz; u=ch[u][tem]; } val[u]=x; } int query(int x) { int u=0; for(int i=31;i>=0;i--){ int tem=