Tire树(字典树)

理论

在这里插入图片描述
上图是一棵Trie树,表示了关键字集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”} 。从上图可以归纳出Trie树的基本性质:

  • 根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
  • 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
  • 每个节点的所有子节点包含的字符互不相同。
  • 从第一字符开始有连续重复的字符只占用一个节点,比如上面的to,和ten,中重复的单词t只占用了一个节点。

模板

//节点
struct Node {//每个节点有26个子节点Node* son[26]{};//末尾标记,可用于区分前缀字符串和完整字符串bool end = false;
};
class Tire {Node* root = new Node();int find(string s) {Node* cur = root;for (char c : s) {int t = c - 'a';if (cur->son[t] == nullptr) {//没找到返回0return 0;}cur = cur->son[t];}//找到完整的返回2,前缀字符串返回1return cur->end ? 2 : 1;}
public://插入字符串void insert(string word) {Node* cur=root;for(char c:word){c-='a';if(cur->son[c]==nullptr){cur->son[c]=new Node();}cur=cur->son[c];}cur->end=true;}//查询完整字符串bool search(string word) {return find(word)==2;}//查询前缀字符串bool startsWith(string prefix) {return find(prefix)!=0;}
};

例题

例题1

爱找事的小Z
题目描述:
小 Z 同学非常喜欢找事,现在有很多名为“事”的字符串,现在小 Z 想要找“事”,请你帮助他判断,他今天是否找了两件相同的事。
输入描述
输入第一行包含一个整数 n,表示小 Z 今天找了多少事。
接下来 n行分别表示 n 件事。
事的输入量不超过 1e3,每个"事"字符串的长度不超过 1000,且所有字母均为小写。
输出描述
若有相同的事输出1,否则输出0。
输入输出样例
示例1
输入

12
acd
acd
asdfsdf
asd
f
saf
asdf
sfasdfs
f
asdf
asf
asdfs

输出

1

示例2
输入

21
adfasdfaasdf
asdfsfas
fa
sdfasd
fsd
fs
a
sda
fsd
afasd
f
sda
f
asdf
as
df
sda
gggggas
dfdsfe
def
a

输出

1

示例
输入

9
asdfasdfa
asdfb
asdc
fasd
fde
sadf
fg
hsadfasdfasdg
iggsadffsa

输出

0
#include<bits/stdc++.h>
using namespace std;
//节点
struct Node {//每个节点有26个子节点Node* son[26]{};//末尾标记,可用于区分前缀字符串和完整字符串bool end = false;
};
class Tire {Node* root = new Node();int find(string s) {Node* cur = root;for (char c : s) {int t = c - 'a';if (cur->son[t] == nullptr) {//没找到返回0return 0;}cur = cur->son[t];}//找到完整的返回2,前缀字符串返回1return cur->end ? 2 : 1;}
public://插入字符串void intsert(string s) {Node* cur = root;for (char c : s) {int t = c - 'a';if (cur->son[t] == nullptr) {cur->son[t] = new Node();}cur = cur->son[t];}cur->end = true;}//查询字符串bool  check(string s) {return find(s) == 2;}
};
int main() {Tire tire;int n;cin >> n;int ans = 0;for (int i = 1; i <= n; i++) {string temp;cin >> temp;if (!tire.check(temp)) {tire.intsert(temp);}else {ans++;}}if (ans) {cout << 1;}else {cout << 0;}return 0;
}

例题2

小蓝的神秘图书馆
问题描述
小蓝是图书馆的管理员,他负责管理图书馆的所有书籍。图书馆有 N本书,每本书都有名字,分别为 S1,S2,…,SN。
图书馆的读者们经常来询问小蓝,他们会给小蓝一个字符串 T,希望小蓝能告诉他们,图书馆里有多少本书的名字是以 T的前缀开头的。小蓝需要回答他们 M次这样的询问。
现在,小蓝需要你的帮助。你能帮助小蓝解决这个问题,从而提升图书馆的服务质量吗?
输入格式
第一行输入两个整数 N 和 M(1≤N,M≤1e4)。
接下来 N 行,每行输入一个字符串 Si,表示图书馆中的一本书的名字。
接下来 M行,每行一个字符串 T,表示读者的询问。
输入字符串的总长度不超过 2×1e5,且仅包含小写字母。
输出格式
对于每个询问,输出一个整数,表示图书馆中以字符串 T开头的书的数量。
每个答案占一行。
样例输入

5 2
ababc
ababd
aba
ab
a
abab
ccc

样例输出

2
0
#include<bits/stdc++.h>
using namespace std;
struct Node {Node* son[26];int end = 0;
};
class Tire {Node* root = new Node();int dfs(Node* cur) {int res = 0;if (cur == nullptr) {return res;}if (cur->end) {res += cur->end;}for (int i = 0; i < 26; i++) {if (cur->son[i]) {res+=dfs(cur->son[i]);}}return res;}
public:void insert(string s) {Node* cur = root;for (char c : s) {c = c - 'a';if (cur->son[c] == nullptr) {cur->son[c] = new Node();}cur = cur->son[c];}cur->end++;}int find(string s) {Node* cur = root;for (char c : s) {c = c - 'a';if (cur->son[c] == nullptr) {return 0;}cur = cur->son[c];}return dfs(cur);}
};
int main() {Tire tire;int n, m;cin >> n >> m;for (int i = 1; i <= n; i++) {string s;cin >> s;tire.insert(s);}for (int i = 1; i <= m; i++) {string s;cin >> s;cout << tire.find(s) << '\n';}return 0;
}
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll N = 2e5 + 10;
string str[N],s[N];
ll n = 0, m = 0;
ll trie[N][27], cnt[N];
ll idx = 2;
void insert(string a){ll p = 1;ll k = a.length() - 1;for (ll i = 1; i <= k; i++){if (!trie[p][a[i] - '0']) trie[p][a[i] - '0'] = idx++;p = trie[p][a[i] - '0'];cnt[p]++;}
}
ll query(string a){ll p = 1;ll k = a.length() - 1;ll ans = 0x3f3f3f;for (ll i = 1; i <= k; i++){p = trie[p][a[i] - '0'];ans = min(ans, cnt[p]);}return ans;
}
int main(){ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cin >> n >> m;for (ll i = 1; i <= n; i++){cin >> str[i];str[i] = '0' + str[i];insert(str[i]);}for (ll i = 1; i <= m; i++){cin >> s[i];s[i] = '0' + s[i];cout << query(s[i]) << endl;}return 0;
}

01Tire

理论

在这里插入图片描述
x >> i & 1
(010)>>30 → (000)&(001) → 0
……
(010)>>2 → (000)&(001) → 0
(010)>>1 → (001)&(001) → 1
(010)>>0 → (010)&(001) → 0

1 << i
(001)<<2 → (100) → 4
(001)<<1 → (010) → 2
(001)<<0 → (001) → 1

res |= (1<< i)
(010)^(101) → (111) → 4+2+1=7
(011)^(101) → (110) → 4+2+0=6
(101)^(010) → (111) → 4+2+1=7
(111)^(010) → (101) → 4+0+1=5

模板

const int N = 1e5 + 10;
int son[32 * N][2], tot = 1;
//插入
void insert(int x)
{int o = 1;for (int i = 30; i >= 0; --i){int y = x >> i & 1;if (!son[o][y])son[o][y] = ++tot;o = son[o][y];}
}//查询
int query(int x)
{int o = 1, res = 0;for (int i = 30; i >= 0; --i){int y = x >> i & 1;//找相反方向的,0找1,1找0,异或后为1,大小最大if (son[o][!y])o = son[o][!y], res |= (1ll << i);//如果该方向没有,则按原有方向走elseo = son[o][y];}return res;
}

例题

XOR最大值
问题描述
给定一个整数数组 arr 和一个整数 q 表示查询的数量。接下来的 q行,每行给出一个整数 x。对于每个 x,你需要找到 arr 中的一个数 y使得 xXORy的值最大,然后输出这个最大值。
输入格式
第一行包含一个整数 n,表示数组 arr 的大小。
第二行包含 n个整数,分别是 arr的元素。(0≤arr[i]≤1e9)。
第三行包含一个整数 q,表示查询的数量。
接下来的 q行,每行包含一个整数 x。(0≤x≤1e9)。
输出格式
对于每个查询输出一行,表示 xXORy 的最大值。
样例输入

5
3 5 7 10 12
3
3
7
10

样例输出

15
13
15
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int son[32 * N][2], tot = 1;void insert(int x)
{int o = 1;for (int i = 30; i >= 0; --i){int y = x >> i & 1;if (!son[o][y])son[o][y] = ++tot;o = son[o][y];}
}int query(int x)
{int o = 1, res = 0;for (int i = 30; i >= 0; --i){int y = x >> i & 1;if (son[o][!y])o = son[o][!y], res |= (1ll << i);elseo = son[o][y];}return res;
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int n;cin >> n;for (int i = 1; i <= n; ++i){int x;cin >> x;insert(x);}int q;cin >> q;while (q--){int x;cin >> x;cout << query(x) << "\n";}
}
#include<bits/stdc++.h>
using namespace std;
struct Node {Node* son[2]{};
};
class Tire {Node* root = new Node();
public:void insert(int x) {Node* cur = root;for (int i = 30; i >= 0; i--) {int y = x >> i & 1;if (!cur->son[y]) {cur->son[y] = new Node();}cur = cur->son[y];}}int query(int x) {Node* cur = root;int res = 0;for (int i = 30; i >= 0; i--) {int y = x >> i & 1;if (cur->son[!y]) {res = res + (1 << i);cur = cur->son[!y];}else {cur = cur->son[y];}}return res;}
};
int main() {Tire tire;ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int n;cin >> n;for (int i = 1; i <= n; ++i){int x;cin >> x;tire.insert(x);}int q;cin >> q;while (q--){int x;cin >> x;cout << tire.query(x) << "\n";}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/74829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

厄瓜多尔主流收单方式:Pago Efectivo支付

PAGOEFECTIVO&#xff08;Pago Efectivo&#xff09;是秘鲁主流的在线支付方式&#xff0c;由El Comercio Group开发&#xff0c;主要为用户提供安全、便捷的在线支付解决方案&#xff0c;支持网银和现金支付&#xff0c;适用于没有信用卡或不愿透露银行信息的消费者。 Pago Ef…

【文献研究】含硼钢中BN表面偏析对可镀性的影响

《B 添加钢的溶融 Zn めっき性に及ぼす BN 表面析出の影響》由JFE公司田原大輔等人撰写。研究聚焦 B 添加钢在低露点退火时 BN 形成对镀锌性的影响&#xff0c;对汽车用高强度钢镀锌工艺优化意义重大。通过多组对比实验&#xff0c;结合多种分析手段&#xff0c;明确了相关因素…

语法: ptr=malloc(size)

MALLOC( ) 语法: ptrmalloc(size) 参数: size是一个整数,表示被分配的字节个数; 返回值: 如果允许的话,返回值是一个指向被分配存储器的指针;否则的话, 返回值是一个非指针; 功能: 该函数用来分配一定大小的空间给一个对象,其大小为size,但该空间的值为不确定值; 有…

JavaScript创建对象与构造函数

目录 创建对象 一、创建对象的 5 种核心方式 1. 对象字面量&#xff08;直接量&#xff09; 2. 使用 Object.create() 3. 工厂模式 4. 构造函数模式 5. ES6 class 语法&#xff08;语法糖&#xff09; 二、构造函数与 new 关键字 1. 构造函数的作用 2. 构造函数的特征…

AIDD-人工智能药物设计-深度学习助力提高儿童低级别胶质瘤复发风险预测的准确性

深度学习助力提高儿童低级别胶质瘤复发风险预测的准确性 儿童低级别胶质瘤&#xff08;pLGG&#xff09;是一种常见于儿童患者中的脑肿瘤&#xff0c;尽管大多数时候被认为是良性肿瘤&#xff0c;但是它们仍然可能导致相关症状和并发症的发生&#xff0c;包括但不限于头疼、癫…

redis的数据类型(1)

https://redis.io/docs/latest/develop/data-types/strings/ 社区版支持&#xff1a; String&#xff0c;字符串 Hash&#xff0c;key-value格式 List&#xff0c;根据插入顺序排序 Set&#xff0c;集合 Sorted set&#xff0c;有排序 Stream&#xff0c; Bitmap&#xff0c; …

Nacos配置中心使用

Nacos配置中心 Nacos除了可以做注册中心,&#x1f517;Nacos下载和注册中心教程,同样可以做配置管理来使用。 一、统一配置管理 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&#xff0c;逐个修改微服务配置就显得十分的不方便&#xff0c;而且很容易出错。我们…

OpenCV轮廓检测全面解析:从基础到高级应用

一、概述 轮廓检测是计算机视觉中的基础技术&#xff0c;用于识别和提取图像中物体的边界。与边缘检测不同&#xff0c;轮廓检测更关注将边缘像素连接成有意义的整体&#xff0c;形成封闭的边界。 轮廓检测的核心价值 - 物体识别&#xff1a;通过轮廓可以识别图像中的独立物体…

Jenkins学习(B站教程)

文章目录 1.持续集成CI2.持续交付CD3.持续部署4.持续集成的操作流程5.jenkins简介6.后续安装部署&#xff0c;见视频 bilibili视频 Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具&#xff0c;起源于Hudson&#xff08;Hudson是商用的&#xff09;&#xff0c;主要用…

ARM-UART

时钟选择PLCK,超时3ms自动发送&#xff0c;设置发送8位的缓冲区&#xff0c;且发送中断 设置触发深度&#xff0c;达到8字节将缓冲区数据发憷 中断处理函数

Rust所有权详解

文章目录 Rust所有权所有权规则作用域 内存和分配移动与克隆栈空间堆空间 关于函数的所有权机制作为参数作为返回值 引用与租借垂悬引用 Rust所有权 C/C中我们对于堆内存通常需要自己手动管理&#xff0c;手动申请和释放&#xff0c;即便有了智能指针&#xff0c;对于效率的影…

【在线OJ项目测试报告】

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家带来关于在线OJ项目的测试报告&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

【HFP】蓝牙HFP应用层核心技术研究

免提配置文件(Hands-Free Profile, HFP)作为实现设备间音频通信的关键协议,广泛应用于车载系统、蓝牙耳机等场景。本文将基于最新技术规范,深入剖析HFP应用层的功能要求、协议映射及编解码器支持,为蓝牙开发工程师提供详尽的技术指南。 一、HFP应用层功能全景图 HFP定义…

横扫SQL面试——PV、UV问题

&#x1f4ca; 横扫SQL面试&#xff1a;UV/PV问题 &#x1f31f; 什么是UV/PV&#xff1f; 在数据领域&#xff0c;UV&#xff08;Unique Visitor&#xff0c;独立访客&#xff09; 和 PV&#xff08;Page View&#xff0c;页面访问量&#xff09; 是最基础也最重要的指标&…

【C++】第八节—string类(上)——详解+代码示例

hello&#xff0c;又见面了&#xff01; 云边有个稻草人-CSDN博客 C_云边有个稻草人的博客-CSDN博客——C专栏&#xff08;质量分高达97&#xff01;&#xff09; 菜鸟进化中。。。 目录 一、为什么要学习string类&#xff1f; 1.1 C语言中的字符串 1.2 面试题(暂不做讲解) …

如何判断JVM中类和其他类是不是同一个类

如何判断JVM中的类是否为同一个类 在Java虚拟机(JVM)中&#xff0c;判断两个类是否相同需要同时满足以下三个条件&#xff1a; 1. 类全限定名必须相同 包括包名类名的完整路径必须完全一致例如&#xff1a;java.lang.String和com.example.String被视为不同类 2. 加载该类的…

ifconfig 使用详解

目录 一、基本语法二、常见用途及示例1. 查看所有网络接口信息2. 启用/禁用网络接口3. 配置 IP 地址和子网掩码4. 修改 MAC 地址5. 启用混杂模式&#xff08;Promiscuous Mode&#xff09;6. 设置 MTU&#xff08;最大传输单元&#xff09; 三、其他选项四、常见问题1. 新系统中…

1. 标准库的强依赖(核心原因)

1. 标准库的强依赖&#xff08;核心原因&#xff09; 容器操作&#xff08;如 std::vector 扩容&#xff09; 当标准库容器&#xff08;如 std::vector&#xff09;需要重新分配内存时&#xff0c;它会尝试移动现有元素到新内存&#xff0c;而非拷贝&#xff08;为了性能&…

【MySQL】常用SQL--持续更新ing

一、配置信息类 1.查看版本 select version; 或 select version(); 2.查看配置 show global variables where variable_name in (basedir,binlog_format,datadir,expire_logs_days,innodb_buffer_pool_size,innodb_log_buffer_size,innodb_log_file_size,innodb_log_files_i…

Day82 | 灵神 | 快慢指针 重排链表

Day82 | 灵神 | 快慢指针 重排链表 143.重排链表 143. 重排链表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者直接给跪了&#xff0c;这个难度真是mid吗 直接去看灵神的视频 环形链表II【基础算法精讲 07】_哔哩哔哩_bilibili 1.简单来说就是&#xf…