Trie 字典树

~~ 比 KMP 简单多了,无脑子选手学不会KMP,不会结论题~~

自己懒得造图了OI WIKI 真棒

字典树大概长这么个亚子



呕吼真棒

  1. 就是将读进去的字符串根据当前的字符是什么和所处的位置构成一棵树
  2. 例如图中\(1-->2-->5\)这一条路就是字符串\(aa\)那\(1-->4-->8-->13\)就是字符串\(cab\)

    貌似也没有什么东西的,题目的话基本就是套板子,唯一奇怪的就是把一个数二级化建树跑一些奇奇怪怪的东西

字符串:

struct Trie{
int trie[][] ,Trie_num;
void add(char *s){
int now = 0 ,
for(int i = 1 ; i <= len ;i++) {
if(!trie[now][s[i]]) trie[now][s[i]] = +++Trie_num;
now = trie[now][s[i]];
}
}
}

二进制:

struct Trie{
int tire[][] ,Tire_num;
void add(int x){
int now = 0 ,
for(int i = 31 ; i >= 0 ;i--) {
int ch = (x>>(i)&1);
if(!tire[now][ch]) tire[now][ch] = +++Trie
now = tire[now][ch];
}
}
}

踹树的时间复杂度其实不低普遍为\(\sum\limits_{i = 1}^{n}~|s_i|\)

例题

题目洛谷也有

这个题就是很显然的板子

  • 询问输入字符串是否为已经输入串的子串
  • 直接边建树边查询就OK

建树并查询的时候会有2种情况

  1. 一直没有添加新的字母一直到该字符的最后一个,说明该字符串为已加入串的子串
  2. 遍历到了某个字符串的最后一个字符,说明已经添加子串为该字符串的子串

然后就没有然后了,你就把它切了(多测不清我是sb)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#define ll long long
using namespace std;
const int N = 1e6+100;
int read() {
int s = 0 , f = 0 ; char ch = getchar() ;
while(!isdigit(ch)) f |= (ch == '-') , ch = getchar();
while(isdigit(ch)) s = s * 10 + (ch ^ 48) , ch = getchar();
return f ? -s : s;
}
char s[20];
struct Trie{
int Tir_num ,tir[N][11],vis[N];
int add(char *s) {
int len = strlen(s+1), now = 0;
bool flag = 0;
for(int i = 1 ; i <= len ;i++) {
int ch = s[i]-'0';
if(!tir[now][ch]) tir[now][ch] = ++Tir_num;
else if(i == len) flag = 1;
// cout << Tir_num<<" ";
now = tir[now][ch];
if(vis[now]) flag = 1;
// cout <<now<<" "<< flag <<" ";
}
vis[now] = 1;
// puts("");
return flag;
}
void clear(){
memset(tir,0,sizeof(tir));
memset(vis,0,sizeof(vis));
Tir_num = 0;
// puts("LKP AK IOI");
}
}tire;
int main() {
int T = read() ;
while(T--) {
tire.clear();
int n = read();
int cnt = 0;
for(int i = 1 ; i <= n;i++){
scanf("%s", s+1);
cnt += tire.add(s);
}
if(cnt) puts("NO");
else puts("YES");
}
system("pause");
return 0;
}

二进制的例题

  • 根据\(xor\)的性质考虑贪心
  • \(1\)^\(1\) \(=0~~\) \(0\) ^ \(1 = 1\) \(~~~~0\) ^ \(0 = 1\)
  • 尽可能的让二级制下的高位存在1

    那么按照这个贪心思路
void query(int x) {
int now = 0 , ans = 0;
for(int i = 31 ; i >= 0 ;i-- ) {
int ch = ((x >> i) & 1) , temp = ch ^ 1;
if(tir[now][temp])
now = tir[now][temp] ,
ans = ((ans << 1) | 1);
else {
now = tir[now][ch];
ans <<= 1;
}
}
return ans;
}

还是贴一下完整代码吧

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#define ll long long
using namespace std;
const int N = 4000010;
int read() {
int s = 0 , f = 0 ; char ch = getchar() ;
while(!isdigit(ch)) f |= (ch == '-') , ch = getchar();
while(isdigit(ch)) s = s * 10 + (ch ^ 48) , ch = getchar();
return f ? -s : s;
}
struct Trie{
int tire[N][2], Tir_num;
void add(int x) {
int now = 0 ;
for(int i = 31 ; i >= 0 ;i--) {
int ch = ((x>>i) & 1);
if(!tire[now][ch]) tire[now][ch] = ++Tir_num;
now = tire[now][ch];
}
}
int query(int x){
int now = 0 , ans = 0;
for(int i = 31 ; i >= 0 ;i--) {
int ch = ( (x >> i) & 1) , temp = ch ^ 1;
if(tire[now][temp]) now = tire[now][temp],ans = (ans << 1) | 1;
else now = tire[now][ch], ans <<= 1;
}
return ans;
}
}tir; int a[N];
int main() {
int n = read();
int ans = -1;
for(int i = 1 ; i <= n ;i++) {
a[i] = read();
tir.add(a[i]);
ans = max(ans,tir.query(a[i]));
}
printf("%d",ans);
system("pause");
return 0;
}

踹树能做的AC自动机也能干,好吧Tire树AC自动机的一部分

自己说的仅仅是一部分,OI wiki讲的很详细,对题目分类讲的也很详细,觉得我写的不好可以去OI wiki

踹树(Trie 字典树)的更多相关文章

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

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

  2. Trie字典树 动态内存

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

  3. 算法导论:Trie字典树

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

  4. 讲解——Trie树(字典树)

          Trie树(字典树) 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找作用的.查找的是啥?单词. 看以下几个题: 1.给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单 ...

  5. 浅谈Trie树(字典树)

          Trie树(字典树) 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找作用的.查找的是啥?单词. 看以下几个题: 1.给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单 ...

  6. [转] 浅谈Trie树(字典树)

    原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html Trie树(字典树) 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找 ...

  7. Trie(字典树)解析及其在编程竞赛中的典型应用举例

    摘要: 本文主要讲解了Trie的基本思想和原理,实现了几种常见的Trie构造方法,着重讲解Trie在编程竞赛中的一些典型应用. 什么是Trie? 如何构建一个Trie? Trie在编程竞赛中的典型应用 ...

  8. TRIE 字典树 前缀紧急集合!

    TRIE: 在计算机科学中,Trie,又称前缀树或字典树,是一种有序树状的数据结构,用于保存关联数组,其中的键通常是字符串.——百度百科 自我理解: trie树,是一种处理字符串前缀的数据结构,通常会 ...

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

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

随机推荐

  1. python对离散数据进行编码

    机器学习中会遇到一些离散型数据,无法带入模型进行训练,所以要对其进行编码,常用的编码方式有两种: 1.特征不具备大小意义的直接独热编码(one-hot encoding) 2.特征有大小意义的采用映射 ...

  2. 粉丝投稿!从2月份的面试被拒到如今的阿里P7,说一说自己学java以来的经验!

    个人近期面试情况 今年二月以来,我的面试除了一个用友的,基本其他都被毙了,可以说是非常残酷的.其中有很多自己觉得还面的不错的岗位,比如百度.跟谁学.好未来等公司.说实话,打击比较大. 情况基本上是从三 ...

  3. container_of 宏

    宏的作用 该宏的作用就是根据结构体中一个成员变量的地址求结构体首地址 如何做到 如果要想根据结构体成员的地址求结构体的首地址,我们需要分三步: 第一步:明确成员变量的地址: 第二步:计算成员变量在该结 ...

  4. 10分钟搞定让你困惑的 Jenkins 环境变量

    前言 Jenkins, DevOps 技术栈的核心之一,CI/CD 离不开编写 Pipeline 脚本,上手 Jenkins ,简单查一下文档,你就应该不会被 agent,stages,step 这类 ...

  5. 使用lua+redis解决发多张券的并发问题

    前言 公司有一个发券的接口有并发安全问题,下面列出这个问题和解决这个问题的方式. 业务描述 这个接口的作用是给会员发多张券码.涉及到4张主体,分别是:用户,券,券码,用户领取记录. 下面是改造前的伪代 ...

  6. spark知识点_RDD

    来自官网的Spark Programming Guide,包括个人理解的东西. 这里有一个疑惑点,pyspark是否支持Python内置函数(list.tuple.dictionary相关操作)?思考 ...

  7. ABP vNext 自动注入,暗藏天坑如斯

    导言 我们在使用ABP vNext框架时,都知道该框架为我们实现了自动依赖注入(实现自动注入需要在项目里面创建Module类,并且将Module类上的DependsOn到相应的启动Module类或调用 ...

  8. C++ 简单输出当前日期时间

    根据https://www.runoob.com/cplusplus/cpp-date-time.html编写. 首先介绍2个数据类型. 一个是time_t,与时间函数相关的变量,定义的变量记录着自 ...

  9. docker搭建前端环境

    开发环境的搭建,是新人入职后的第一道槛,有时一个小小的问题就能阻塞半天.如果能提供一个工具在短时间内搞定开发环境,势必提高新人对团队的印象分!docker就是这样一个工具. 镜像&容器 doc ...

  10. python模块详解 | pyquery

    简介 pyquery是一个强大的 HTML 解析库,利用它,我们可以直接解析 DOM 节点的结构,并通过 DOM 节点的一些属性快速进行内容提取. 官方文档:http://pyquery.readth ...