Trie (字典树,前缀树)
一,内容
(一),概念
详情可见:详解Trie
插入过程(insert)
对于一个单词,从根开始,沿着单词的各个字母所对应的树中的节点分支向下走,直到单词遍历完,将最后的节点进行标记,表示该单词已插入Trie树。
查询过程 (query)
同样的,从根开始按照单词的字母顺序向下遍历trie树,一旦发现某个节点标记不存在或者单词遍历完成而最后的节点未被标记,则表示该单词不存在; 若最后的节点被标记了,表示该单词存在。
特点:
根节点不包含字符,每条边代表一个字符。
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
每个节点的所有子节点包含的字符都不相同。
(二), 代码
#include<stdio.h>
#include<string.h>
const int maxn = 1000010;
struct Trie
{
int sz;//编号
int ch[maxn][26];
int val[maxn];
//val为附加信息
//这里的ch数组,第二维的大小为26是因为字符串只由小写字母构成,第二维的大小一般是由字符串的组成决定
//sz即为节点编号
Trie()
{
sz = 1;//一开始的时候只有根节点这一个节点
memset(ch[0], 0, sizeof(ch[0]));
memset(val, 0, sizeof(val));
}//这里是初始化
int idx(char c) {//简易转化,将a到z转化为0到25.
return c - 'a';
}
void insert(char* s,int v) {//插入操作 ,这里是整份代码中唯二用到指针的地方,因为函数是放在结构体里面 ,所以最好用个指针,其实等价于char s[]
//s代表要插入的字符串,如果有需要可以增加int v为附加信息
int u = 0, n = strlen(s);
for (int i = 0; i < n; i++) {//如果节点不存在就插入,不然就继续往下遍历
int c = idx(s[i]);
if (!ch[u][c]) {
memset(ch[sz], 0, sizeof(ch[sz]));
ch[u][c] = sz++;//新建节点
}
u = ch[u][c];//非常重要,是到下一层,如果写成sz则便会隔一层。//往下遍历
}
val[u] = v;//在节点末尾
//插入附加信息,注意,我们一般只在叶子节点插入附加信息,中间的节点一般是没有附加信息的,
//因为一个非叶子结点,在Trie中一般都会被不同的单词使用到(定义)
}
long long search(char* s) {//这里的指针意义同上
//对于这一个查找操作,我们就以最简单的操作来展开:
//查找这个字符串是否在Trie中出现过,如果出现过,返回它的附加信息
long long u = 0, len = strlen(s + 1);
for (long long i = 1; i <= len; i++) {
long long c = idx(s[i]);
if (!ch[u][c])return -1;
//没有这个节点,返回-1,即代表这个字符串没有在Trie中出现过
//这个返回值得看题目所需要的附加信息来决定,因为这里是不可以与附加信息冲突的,在这里我们假定附加信息为0或正数
u = ch[u][c];//继续向下遍历
}
return val[u];//这个节点存在,返回它的附加信息
}
};
二, 例题
luogu P2580 于是他错误的点名开始了
#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define mt(x,y) memset(x,y,sizeof(x))
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
il void read(ll &x){//快读 x=0;ll f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}x*=f;
}
using namespace std;
#define N 500010
struct Trie{ll val[N],ch[N][26],sz;Trie(){sz=1;memset(ch[0],0,sizeof(ch[0]));memset(val,0,sizeof(val));}//初始化 ll idx(char c){return c-'a';}void insert(char *s){ll u=0,len=strlen(s+1);for(ll i=1;i<=len;i++){ll c=idx(s[i]);if(!ch[u][c]){memset(ch[sz],0,sizeof(ch[sz]));
// val[sz]=0; 这里并不需要这么标记中间信息,因为在初始化
//那里已经将所有的附加信息初始化为0了 ch[u][c]=sz++;}u=ch[u][c];}}ll search(char *s){ll u=0,len=strlen(s+1);for(ll i=1;i<=len;i++){ll c=idx(s[i]);if(!ch[u][c])return 0;//如果没有这个节点,也就意味着询问的这个字符串不存在,输出WRONG u=ch[u][c];}if(!val[u]){val[u]=1;return 1;//这个字符串已经询问过了,标识一下,然后输出OK }return 2;//这个字符串正确,但不是第一次出现,输出REPEAT }
}tree;
ll n,m;
int main(){read(n);char s[100];for(ll i=1;i<=n;i++){scanf("%s",s+1);tree.insert(s);}read(m);for(ll i=1;i<=m;i++){scanf("%s",s+1);ll pd=tree.search(s);if(pd==0)printf("WRONG\n");else if(pd==1)printf("OK\n");else if(pd==2)printf("REPEAT\n");}return 0;
}
Trie (字典树,前缀树)相关推荐
- Trie(字典树/前缀树)
字典树/前缀树 Trie(发音类似 "try")或者说 前缀树(字典树) 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键.这一数据结构有相当多的应用情景,例如自动补完和 ...
- 字典数(前缀树)的实现
[题目] 字典树又称为前缀树或者Trie树,是处理字符串常用的数据结构.假设组成所有单词的字符仅是'a'-'z',请实现字典树的结构,并包含以下四个主要的功能. void insert(String ...
- Trie(前缀树/字典树)及其应用
from:https://www.cnblogs.com/justinh/p/7716421.html Trie,又经常叫前缀树,字典树等等.它有很多变种,如后缀树,Radix Tree/Trie,P ...
- 提高篇 第二部分 字符串算法 第3章 Trie字典树
Trie(字典树)解析及其在编程竞赛中的典型应用举例 - Reqaw - 博客园 『一本通』Trie字典树 - YeLingqi - 博客园 字典树(Trie Tree) - 仰望高端玩家的小清新 - ...
- 字典树实现_【Leetcode每日打卡】单词的压缩编码 Trie(字典树)入门
一.前言(鸡汤(一段废..话..可以跳过啦)) 同学们好!没想到我这个小小的公众号破千粉啦,对于大佬们而言或许不值一提,但是对我而言是一个莫大的鼓舞!更加坚定了我持续输出优质内容的决心.希望我们都能每 ...
- trie树查找前缀串_Trie数据结构(前缀树)
trie树查找前缀串 by Julia Geist Julia·盖斯特(Julia Geist) A Trie, (also known as a prefix tree) is a special ...
- python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie)...
python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie) 主要包括两部分内容: (1)利用python中的dict实现Trie: ( ...
- C++简单实现 前缀树
今天在leetcode上面看了一道题(第208题),问题是如何实现一个字符串前缀树,能够实现字符串的插入,查找和查找前缀功能.在这里记录一下前缀树的实现: class Trie { public:/* ...
- 前缀树介绍,定义,图文详解分析——Java/Kotlin双版本代码
前缀树 前缀树,又称作字典树,用一个树状的数据结构储存字典中的所有单词. 列,一个包含can.cat.come.do.i.in.inn的前缀树如下图所示: 前缀树是一个多叉树,一个节点可能存在多个节点 ...
- 【前缀树】写一个敏感词过滤器
1.什么是敏感词过滤 这其实是一个很常见的功能,随处可见以至于你可能都没关注过,基本上在有评论的地方都会有它的身影. 举例来说,你打游戏和别人对喷的时候,是不是一些脏话发不出去哈哈,这些词汇会用*** ...
最新文章
- python学习-25 函数递归
- mysql中date转sqlserver_MySQL和SQLServer互转
- 【c++】重载操作符
- 多层陶瓷电容器用处_陶瓷电容的作用及特点
- 为什么vs2005内置Web application server中调用COM组件时正常,在IIS中运行时组件创建失败?...
- DWZ中Tree树形菜单的treeCheck如何获取返回值解决方案
- 机器人防火墙:人机识别在应用安全及风控领域的一点实践
- C语言 main 函数到底为啥这么写?
- http请求中的Query String Parameters、Form Data、Request Payload
- Eclipse 如何修改默认工作空间和切换工作空间(Workspace)
- java 生成验证码
- 九、Linux的网络配置
- C# lable及时显示 lable实时刷新
- 39个seo大师级经典案例
- SQLServer------Sql Server性能优化辅助指标SET STATISTICS TIME ON和SET STATISTICS IO ON
- MicroDicom viewer(Dicom格式看图软件) v3.4.7官方版
- 奇异值分解(SVD)(2)
- 文本乱码怎么办?教你一招批量修改文本文件的编码格式,轻松解决乱码问题
- 46. 孩子们的游戏-圆圈中最后剩下的数字
- fastreport 横向打印多列