Trie树

字典树

  • 本质上就是树上路径字符串版本
  • 特定的路径表示完整的字符串,同层的相同字母合并为一个一样的字母。

B. 数字串前缀匹配 || 【一本通提高篇Trie字典树】Phone List

这题看似简单,但是调了好久。

我们正常建树,如果在遍历到某一个结点的过程中检测到当前作为一个字符串的末尾 \((cnt[p] ≠ 0)\) 。我们就认定该字符串有前缀在给出数据中。

要注意的细节:

  • 多测清空。建议手动清空,\(memset\) 出题人卡常专用
  • 数组大小谨慎开,动不动就MLE。
  • 记得判断:两个串相同也要输出NO!
#include <bits/stdc++.h>
using namespace std;
int n, a[101010][70], cnt[101010], idx;
bool f = false;
char s[101010]; void insert() {
int p = 0, x;
int old = idx;
for (int i = 0; s[i]; i++) {
x = s[i] - '0';
if (a[p][x] == 0) a[p][x] = ++idx;
if (cnt[p] != 0) {
f = true;
return ;
}
p = a[p][x];
}
if(old == idx){
f = true;
return ;//没有新建任何结点
}
cnt[p]++;
}
int main() {
int t;
cin >> t;
while (t--) {
f = 0;
memset(a,0,sizeof a);
memset(cnt,0,sizeof cnt);
idx = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> s;
insert();
}
if (!f) puts("YES");
else puts("NO");
}
}

P8306 【模板】字典树

  • 板子。我们在插入字符串的时候每添加(遍历)到一个字符,就将它对应的节点编号++,这样我们就能在一个位置得到有多少个单词到现在为止的前缀与它到现在为止的前缀相同。当前单词结尾时就能得到他相同前缀单词的数量。
#include <bits/stdc++.h>
using namespace std;
char s[3000010];
int a[3000010][90];
int idx;//节点编号
int cnt[3000010];
void insert(char s[]) {
int p = 0, c;
for (int i = 0; s[i]; i++) {
c = s[i] - '0';
if (a[p][c] == 0) a[p][c] = ++idx;
p = a[p][c];
cnt[p]++;
} }
int query(char s[]) {
int d = 0, c;
for (int i = 0; s[i]; i++) {
c = s[i] - '0';//恶心题,字符串包含数字
if (a[d][c] == 0) return 0;
else d = a[d][c];
}
return cnt[d];
}
int main() {
int t;
cin >> t;
while (t--) {
for (int i = 0; i <= idx; i++) {
for (int j = 0; j < 90; j++) {
a[i][j] = 0;
}
} for (int i = 0; i <= idx; i++) {
cnt[i] = 0;
}
idx = 0;
int n;
cin >> n; int m;
cin >> m;
for (int i = 1; i <= n; i++) {
cin >> s;
insert(s);
} for (int i = 1; i <= m; i++) {
cin >> s;
cout << query(s) << "\n";
}
}
}

A. 三年二班的投票

板子。

#include <bits/stdc++.h>
using namespace std;
int n, ch[1000010][30], cnt[1000010];
char s[1000010];
int idx;
void insert() {
int p = 0;
for (int i = 0; s[i]; i++) {
int x = s[i] - 'a';
if (ch[p][x] == 0) ch[p][x] = ++idx;
p = ch[p][x];//下移到当前节点(下一次起点)
}
cnt[p]++;//节点编号++
}
int query() {
int x, p = 0;
for (int i = 0; s[i]; i++) {
x = s[i] - 'a';
if (ch[p][x] == 0) return 0;
p = ch[p][x];
}
return cnt[p];
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%s", s);
insert();
}
cin >> n;
for (int i = 1; i <= n; i++) {
scanf("%s", s);
printf("%d\n", query());
} return 0;
}

F. 字典树I

纯唐板子。

#include <bits/stdc++.h>
using namespace std;
int n,a[1010010][30],cnt[1010101],op;
char s[1001010];
int idx;//节点编号
void insert(char s[]){
int x,p = 0;
for(int i= 0;s[i];i++){
x = s[i]-'a';
if(a[p][x] == 0) a[p][x] = ++idx;
p = a[p][x];
}
cnt[p]++;
}
int query(char s[]){
int x,p = 0;
for(int i = 0;s[i];i++){
x = s[i]-'a';
if(a[p][x] == 0) return 0;
p = a[p][x];
}
return cnt[p];
}
int main(){
cin>>n;
for(int i = 1;i <= n;i++){
cin>>op>>s;
if(op == 1){
insert(s);
}else cout<<(query(s) ? "Yes" : "No")<<"\n";
}
}

G. 字典树II

弱化版本P8306 【模板】字典树,对数组大小和 \(memset\) 常数没有特殊卡常。

#include <bits/stdc++.h>
using namespace std;
int n,a[101010][30],cnt[1010101],op;
char s[101010];
int idx;//节点编号
void insert(char s[]){
int x,p = 0;
for(int i= 0;s[i];i++){
x = s[i]-'a';
if(a[p][x] == 0) a[p][x] = ++idx;
p = a[p][x];
cnt[p]++;
} }
int query(char s[]){
int x,p = 0;
for(int i = 0;s[i];i++){
x = s[i]-'a';
if(a[p][x] == 0) return 0;
p = a[p][x];
}
return cnt[p];
}
int main(){
cin>>n;
for(int i = 1;i <= n;i++){
cin>>op>>s;
if(op == 1){
insert(s);
}else cout<<query(s)<<"\n";
}
}

Trie树做题记录的更多相关文章

  1. Sam做题记录

    Sam做题记录 Hihocoder 后缀自动机二·重复旋律5 求一个串中本质不同的子串数 显然,答案是 \(\sum len[i]-len[fa[i]]\) Hihocoder 后缀自动机三·重复旋律 ...

  2. 退役IV次后做题记录

    退役IV次后做题记录 我啥都不会了.... AGC023 D 如果所有的楼房都在\(S\)同一边可以直接得出答案. 否则考虑最左最右两边的票数,如果左边>=右边,那么最右边会投给左边,因为就算车 ...

  3. 退役III次后做题记录(扯淡)

    退役III次后做题记录(扯淡) CF607E Cross Sum 计算几何屎题 直接二分一下,算出每条线的位置然后算 注意相对位置这个不能先搞出坐标,直接算角度就行了,不然会卡精度/px flag:计 ...

  4. 退役II次后做题记录

    退役II次后做题记录 感觉没啥好更的,咕. atcoder1219 历史研究 回滚莫队. [六省联考2017]组合数问题 我是傻逼 按照组合意义等价于\(nk\)个物品,选的物品\(\mod k\) ...

  5. BJOI做题记录

    BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...

  6. FJOI2017前做题记录

    FJOI2017前做题记录 2017-04-15 [ZJOI2017] 树状数组 问题转化后,变成区间随机将一个数异或一,询问两个位置的值相等的概率.(注意特判询问有一个区间的左端点为1的情况,因为题 ...

  7. HDU 1251 统计难题 (Trie树模板题)

    题目链接:点击打开链接 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单 ...

  8. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  9. UOJ 做题记录

    UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...

  10. HDU 1251 Trie树模板题

    1.HDU 1251 统计难题  Trie树模板题,或者map 2.总结:用C++过了,G++就爆内存.. 题意:查找给定前缀的单词数量. #include<iostream> #incl ...

随机推荐

  1. 从找朋友到找变位词:一道趣味字符串问题的深入解析|LeetCode 438 找到字符串中所有字母异位词

    LeetCode 438 找到字符串中所有字母异位词 点此看全部题解 LeetCode必刷100题:一份来自面试官的算法地图(题解持续更新中) 生活中的算法 还记得小时候玩的"找朋友&quo ...

  2. ATT&CK实战系列(一)

    环境下载 下载靶场环境,并导入虚拟机分别是win2003.win7.winserver2008 配置网络 虚拟机--编辑--虚拟机网络编辑器--添加网络VMnet2--仅主机模式分配的地址是192.1 ...

  3. PADS无模命令总结表

    无模命令总结表 1.C 补充格式,在内层负片设计时用来显示 Plane 层的焊盘及 Thermal.使用方法是,从键盘上输入 C 显示,再次输入 C 可去除显示. 2.D 打开/关闭当前层显示,使用方 ...

  4. Vue实现企业微信扫码登录

        Vue实现企业微信扫码登录   企业微信扫码登录原理 构建企业微信登录二维码 获取访问令牌access_token 请求方式:GET(HTTPS)请求URL:https://qyapi.wei ...

  5. DataX - [01] 概述

      DataX是阿里巴巴集团内被广泛使用的离线数据同步工具/平台.实现包括MySQL.Oracle.SQLServer.PostgreSQL.HDFS.Hive.ADS.HBase.TableStor ...

  6. 非容器环境中使用Selenium,提升Chrome与ChromeDiver兼容性

    背景 在 Windows 环境下使用 Selenium 时,Chrome 浏览器版本与 ChromeDriver 版本的兼容性问题是一个常见的困扰. 由于 Chrome 频繁更新,而 ChromeDr ...

  7. ITSS 运维-服务台相关内容

  8. linux php安装mongodb 扩展

    下载扩展 首先从这个网站选择适合你当前 php 版本的的 mongodb 扩展 https://pecl.php.net/package/mongodb wget https://pecl.php.n ...

  9. Python数据格式转换神器-提高办公效率

    一.引言 在工作日常里,数据转换总是让人头疼?别急,今天揭秘一个超级实用的Python技巧,帮你轻松搞定各种数据格式转换,提升工作效率不是梦! 场景1:你手头有一堆CSV格式的(逗号分隔符)数据,其他 ...

  10. PostgreSQL下载

    官方下载地址: https://www.postgresql.org/download/pgAdmin4客户端工具下载地址:https://www.pgadmin.org/download/pgadm ...