c语言 trie树,数据结构篇——字典树(trie树)
引入
现在有这样一个问题, 给出$n$个单词和$m$个询问,每次询问一个单词,回答这个单词是否在单词表中出现过。
好像还行,用 map ,几行就完事了。
那如果n的范围是 $10^5$ 呢?再用 $map$ 妥妥的超时,说不定还会超内存。
这时候就需要一种强大的数据结构——字典树
基本性质
字典树,又叫Trie树、前缀树,用于统计,排序和保存大量的字符串,经常被搜索引擎系统用于文本词频统计。
基本思想: 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。
假设所有单词都只由小写字母构成,由(abd,abcd,b,bcd,efg,hil)构成的字典树如下。(百科的图最后少了一个字母,姑且认为它是'l'吧)
可以看出字典树具有以下特点:
用边表示字母
具有相同前缀的单词共用前缀节点
每个节点最多有26个子节点(在单词只包含小写字母的情况下)
树的根节点是空的
基本操作
数据结构定义
用pass记录有多少字符串经过该节点,就是多少单词以根结点到该结点的边组成的字符串为前缀。
用end记录有多少字符串以该节点结尾,就是多少单词是以根结点到该结点的边组成的字符串。
typedef struct node{
int pass;//有多少单词经过该结点
int end;//有多少单词以该结点结尾
struct node* next[26];
}*trieTree;
插入
向字典树中插入字符串 $S$
void insert(trieTree T,string s) {
node *n = T;
for (int i = 0; i < s.length(); i++) {
int index = s[i] - 'a';
if (T->next[index] == NULL) {
node *t = new node();
T->next[index] = t;
}
T = T->next[index];
T->pass++;
}
T->end++;
}
查找
查找文章中有多少单词以字符串 $S$ 为前缀。
如果要查找字符串 $s$ 在文章中出现了多少次,则返回值改成 T->end 。
int find(trieTree T, string s) {
node *n = T;
for (int i = 0; i < s.length(); i++) {
int index = s[i] - 'a';
if (T->next[index] == NULL) {
return NULL;
}
T = T->next[index];
}
return T->pass;
}
完整实现
#include
#include
using namespace std;
typedef struct node{
int pass;
int end;
struct node* next[26];
}*trieTree;
void insert(trieTree T,string s) {
node *n = T;
for (int i = 0; i < s.length(); i++) {
int index = s[i] - 'a';
if (T->next[index] == NULL) {
node *t = new node();
T->next[index] = t;
}
T = T->next[index];
T->pass++;
}
T->end++;
}
int find(trieTree T, string s) {
node *n = T;
for (int i = 0; i < s.length(); i++) {
int index = s[i] - 'a';
if (T->next[index] == NULL) {
return NULL;
}
T = T->next[index];
}
return T->pass;
}
map实现
用 node* next[26] 会浪费很多空间,因为不可能每个结点都用掉 26 个 next
#include
#include
#include
using namespace std;
typedef struct node{
public:
int pass;
int end;
mapm;
}* trieTree;
void insert(trieTree T,string s) {
for (int i = 0; i < s.length(); i++) {
if (T->m.find(s[i]) == T->m.end()) {
node *t = new node();
T->m.insert(make_pair(s[i], t));
}
T = T->m[s[i]];
T->pass++;
}
T->end++;
}
int find(trieTree T, string s) {
node *n = T;
for (int i = 0; i < s.length(); i++) {
if (T->m.find(s[i]) == T->m.end()) {
return NULL;
}
T = T->m[s[i]];
}
return T->pass;
}
适用例题
前缀匹配、 字符串检索 、词频统计,这些差不多都是一类题目,具体实现有一点点不同。
比如前缀匹配,我们只需要pass就行了,用不到end;词频统计的话,我们又只用得到end了;如果只是字符串检索的话,那更方便了,end定义成bool变量就行了。具体用啥,怎么用要变通。
这题有点小坑,用 node* next[26] 交G++会超内存,交C++就不会。但确实用数组会浪费很多空间,推荐使用map实现。
#include
#include
#include
using namespace std;
typedef struct node{
int pass;
mapm;
}*trieTree;
void insert(trieTree T,string s) {
for (int i = 0; i < s.length(); i++) {
if (T->m.find(s[i]) == T->m.end()) {
node *t = new node();
T->m.insert(make_pair(s[i], t));
}
T = T->m[s[i]];
T->pass++;
}
}
int find(trieTree T, string s) {
node *n = T;
for (int i = 0; i < s.length(); i++) {
if (T->m.find(s[i]) == T->m.end()) {
return NULL;
}
T = T->m[s[i]];
}
return T->pass;
}
int main() {
trieTree T = new node();
string s;
while (getline(cin,s)) {
if (s.empty()) break;
insert(T, s);
}
while (getline(cin,s)) {
cout << find(T, s) << endl;
}
return 0;
}
此外,还适用于字符串排序,字典树是一棵多叉树,只要先序遍历整棵树,输出相应的字符串便是按字典序排序的结果。
c语言 trie树,数据结构篇——字典树(trie树)相关推荐
- 北京大学肖臻老师《区块链技术与应用》公开课笔记17——ETH数据结构篇1(状态树1)
北京大学肖臻老师<区块链技术与应用>公开课笔记 以太坊数据结构篇1--状态树1,对应肖老师视频:click here 全系列笔记请见:click here 以太坊数据结构篇1--状态树2请 ...
- 用Python实现字典树(Trie)与双数组字典树(DATrie)
1. 字典树(Trie) 假如我们把字典中的词以记录的形式(无序)存入数据库中.现给定一串字符,要查找该字符串是否为字典中的词.因为数据库中的记录是无序的,所以,最朴素的方法就逐记录匹配.此方法简单, ...
- Trie树 -- 高效的字典树
文章目录 简介 原理 构造一棵Trie树 使用Trie树进行查询 实现 模拟(瞎暴力)实现 空间优化 简介 Trie树是一种数据结构,它有一个好听的中文名字,叫"字典树".顾名思义 ...
- 【字典树】用python实现Trie树
字典树常用做高效的文本词语保存,适用于敏感词过滤.关键词提取等场景.在字典树中相同前缀的词之间共享相同的树节点和路径. 字典树结构一般包括如下功能和属性:(1)构建:(2)添加:(3)删除:(4)前缀 ...
- [2020-11-23 contest]图(dfs剪枝),劫富济贫(字典树),小A的树(树形DP),游戏(贪心/斜率优化)
文章目录 T1:图 solution code T2:劫富济贫 solution code T3:小A的树 solution code T4:游戏 solution code T1:图 [问题描述] ...
- 字典树实现_trie 字典树的实现方法
trie 字典树 (前缀树) 什么是字典树 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文 ...
- 012-数据结构-树形结构-哈希树[hashtree]、字典树[trietree]、后缀树
一.哈希树概述 1.1..其他树背景 二叉排序树,平衡二叉树,红黑树等二叉排序树.在大数据量时树高很深,我们不断向下找寻值时会比较很多次.二叉排序树自身是有顺序结构的,每个结点除最小结点和最大结点外都 ...
- 数据结构——从英文字典树到中文字典树
昨天面试电话中的一道题,题目如下: 1.给你一个姓名的集合,查找你的名字是否在里面出现. 我的回答是用set,把集合中所有的姓名放到set集合中,直接用find查找我的姓名在这个集合里面是否出现. 2 ...
- 总结下各种常见树形结构的定义及特点(二叉树、AVL树、红黑树、Trie树、B树、B+树)
文章目录 前言 一棵普通的树 相关术语 二叉树 二叉树性质 二叉树特例 二叉查找树 AVL树 特点及应用 红黑树 特点 应用 Trie树 特点及应用 B树 定义及特点 应用 B+树 B+树的优势及应用 ...
最新文章
- java怎么创建子程序_JVM执行子程序
- 简单的Tab切换组件
- 大话Web-Audio-Api
- 从Github一开源项目ADSEC【学习域渗透攻防基础】
- 《看聊天记录都学不会Python到游戏实战?太菜了吧》(7)我用函数写了个特洛伊木马
- nyoj 586 疯牛(二分+贪心)
- java中国象棋网络对弈,java课程设计---中国象棋对弈系统
- 深入理解redux之从redux源码到react-redux的原理
- 比特币锚定币总锁仓量触及38亿美元 创历史新高
- 180.连续出现的数字
- Axure8授权激活码
- Xcode低版本运行高版本真机(xcode9联调真机iOS12 系统)
- Agilent E3649A via RS232 to PC 通信终于知道错哪了
- python爬虫:批量刷新网页
- 百分点认知智能实验室出品:智能问答中的对抗攻击及防御策略
- pio读取 Excel中 电话号码和身份证的问题
- 平衡小车c语言程序,【全部开源】两轮平衡小车(原理图、PCB、程序源码、BOM等)...
- CSS——引入ico图标
- 利用R语言制作GGEBiplot-双标图教程
- 【Zabbix】Zabbix微信告警配置演示