什么是trie?

百度百科

又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

trie有什么用处?

①进行快速的查找字符串是否存在

②进行快速的字符串的前缀和的相关的性质的查询

如何实现trie?

导言

trie是靠二维数组进行存储的,其中trie[a][b]=c,指的是a的第b个孩子的编号是c。特别的trie是用边来存储字符而并不是节点!编号代表的是a-z的26个字母中的第几个字母所以编号是从0-25。

百度百科的图片

①insert函数

insert函数代表着插入操作。如何实现呢?

(1)把需要插入的string拆分成一个又一个的单个的字符进行操作。并且把rt初始化为0

int rt=0;
for(int i=0;i<a.size();i++)
{
//....
}

(2)计算id编号(注意这个地方是-'a'不是-'0')

int id=a[i]-'a';

(3)循环判断当前的父节点是不是存在一条以id编号的边,如果不存在那么,添加一个这样的边并且把子节点赋予一个编号

if(!trie[rt][id])
trie[rt][id]=++tot;

(4)将rt层层递进

rt=trie[rt][id];

insert函数完整代码

void insert(string a)
{
int rt=0;
for(int i=0;i<a.size();i++)
{
int id=a[i]-'a';
if(!trie[rt][id])
trie[rt][id]=++tot;
rt=trie[rt][id];
}
}

②search函数

search函数代表着查询的操作,这里我们查询当前前缀是不是在树中,当然trie可以做很多别的操作,结合insert函数,如何实现?

(1)(2)同insert函数

  int rt=0;
for(int i=0;i<a.size();i++)
{
int id=a[i]-'a';
//.....
}

(3)查询相应的编号的边是不是这个父节点的儿子,如果不是那么返回0

if(!trie[rt][id])
return 0;

(4)层层递进同insert

rt=trie[rt][id];

(5)如果这个字符串能安全的走出循环,那么就返回1,说明这个前缀是存在的

search函数完整代码

int search(string a)
{
int rt=0;
for(int i=0;i<a.size();i++)
{
int id=a[i]-'a';
if(!trie[rt][id])
return 0;
rt=trie[rt][id];
}
return 1;
}

trie模板完整代码(注意此处的map效率过慢,应该直接开数组为妙)

#include <bits/stdc++.h>
using namespace std;
map<int,map<int,int> > trie;
map<int,int> sum;
int tot;
void insert(string a)
{
int rt=0;
for(int i=0;i<a.size();i++)
{
int id=a[i]-'a';
if(!trie[rt][id])
trie[rt][id]=++tot;
rt=trie[rt][id];
}
}
int search(string a)
{
int rt=0;
for(int i=0;i<a.size();i++)
{
int id=a[i]-'a';
if(!trie[rt][id])
return 0;
rt=trie[rt][id];
}
return 1;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
string a;
cin>>a;
insert(a);
}
for(int i=0;i<m;i++)
{
string a;
cin>>a;
if(search(a))
cout<<"YES\n";
else
cout<<"NO\n";
}
}

拓展

①查询相应前缀所包含的字符串的数量(hdu 1251 统计难题)

只需要在insert函数中设定一个sum数组,保存每个节点遍历过的次数,即sum[trie[rt][id]]++,然后在search函数中寻找到字符串最后的节点返回sum[rt]即可。只要中间出现没有在树中的字符直接return0

②查询相应的单词是否在树中

只需要在insert函数中设置一个记录词尾的数组即可,然后search函数中找到最后如果这个词尾存在的话那么就是存在否则就是不存在

trie字典树模板浅析的更多相关文章

  1. [trie]字典树模板

    #include<bits/stdc++.h> using namespace std; typedef long long ll; struct trie{ int count; tri ...

  2. CH 1601 - 前缀统计 - [字典树模板题]

    题目链接:传送门 描述给定 $N$ 个字符串 $S_1,S_2,\cdots,S_N$,接下来进行 $M$ 次询问,每次询问给定一个字符串 $T$,求 $S_1 \sim S_N$ 中有多少个字符串是 ...

  3. hdu1521(字典树模板)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1251 题意: 中文题诶~ 思路: 字典树模板 代码1: 动态内存, 比较好理解一点, 不过速度略慢, ...

  4. Trie 字典树,hdu1251

    参考博客:https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html 字典树就是单词树,顺着一条路径到达终止结点就形成一个单词,该单词的前缀包含在这 ...

  5. 萌新笔记——C++里创建 Trie字典树(中文词典)(一)(插入、遍历)

    萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...

  6. Trie字典树 动态内存

    Trie字典树 #include "stdio.h" #include "iostream" #include "malloc.h" #in ...

  7. 算法导论:Trie字典树

    1. 概述 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树. Trie一词来自retrieve,发音为/tr ...

  8. 字典树模板题(统计难题 HDU - 1251)

    https://vjudge.net/problem/HDU-1251 标准的字典树模板题: 也注意一下输入方法: #include<iostream> #include<cstdi ...

  9. 标准Trie字典树学习二:Java实现方式之一

    特别声明: 博文主要是学习过程中的知识整理,以便之后的查阅回顾.部分内容来源于网络(如有摘录未标注请指出).内容如有差错,也欢迎指正! 系列文章: 1. 标准Trie字典树学习一:原理解析 2.标准T ...

随机推荐

  1. ubuntu14安装docker-ce

    先卸载旧的docker sudo apt-get remove docker docker-engine docker.io docker-ce 通过HTTPS使用存储库(repository) su ...

  2. [Codeforces 425A] Sereja and Swaps

    [题目链接] https://codeforces.com/contest/425/problem/A [算法] 枚举最终序列的左端点和右端点 , 尝试用这段区间中小的数与区间外大的数交换 时间复杂度 ...

  3. 编译Ruby2.0 问题解决

    compiling readline.creadline.c: In function ‘Init_readline’:readline.c:1886:26: error: ‘Function’ un ...

  4. 使用JS准确获取URL网址中参数的几种方法

    记录下使用JS准确获取URL网址中参数的方法: 参考链接1. https://blog.csdn.net/Zhihua_W/article/details/54845945?utm_source=bl ...

  5. SQLAlchemy 反向生成 model 模型

    前言 Django 反向生成的 model 模型的命令 :  python manager.py inspectdb SQLAlchemy / Flask-SQLAlchemy则是: pip3 ins ...

  6. bzoj 1710: [Usaco2007 Open]Cheappal 廉价回文【区间dp】

    只要发现添加一个字符和删除一个字符是等价的,就是挺裸的区间dp了 因为在当前位置加上一个字符x就相当于在他的对称位置删掉字符x,所以只要考虑删除即可,删除费用是添加和删除取min 设f[i][j]为从 ...

  7. angularjs2 不同组件间的通信

    AngualrJs2官方方法是以@Input,@Output来实现组件间的相互传值,而且组件之间必须父子关系,下面给大家提供一个简单的方法,实现组件间的传值,不仅仅是父子组件,跨模块的组件也可以实现传 ...

  8. Oracle虚拟机配置

    1.正常安装 .配置 3.监听配置 4.重启监听服务 5.防火墙端口放行 6.Oracle客户端连接工具测试

  9. 树形DP UVA 1292 Strategic game

    题目传送门 /* 题解:选择一个点,它相邻的点都当做被选择,问最少选择多少点将所有点都被选择 树形DP:dp[i][0/1]表示当前点选或不选,如果选,相邻的点可选可不选,取最小值 */ /***** ...

  10. 利用freemarker导出页面格式复杂的excel

    刚开始大家可能会利用poi生成简单的excel,但是遇到需要生成复杂的excel,poi导出excel就比较困难,这时候可以利用freemarker来渲染实现实现生成复杂的excel, 首先,将exc ...