Trie树做题记录
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树做题记录的更多相关文章
- Sam做题记录
Sam做题记录 Hihocoder 后缀自动机二·重复旋律5 求一个串中本质不同的子串数 显然,答案是 \(\sum len[i]-len[fa[i]]\) Hihocoder 后缀自动机三·重复旋律 ...
- 退役IV次后做题记录
退役IV次后做题记录 我啥都不会了.... AGC023 D 如果所有的楼房都在\(S\)同一边可以直接得出答案. 否则考虑最左最右两边的票数,如果左边>=右边,那么最右边会投给左边,因为就算车 ...
- 退役III次后做题记录(扯淡)
退役III次后做题记录(扯淡) CF607E Cross Sum 计算几何屎题 直接二分一下,算出每条线的位置然后算 注意相对位置这个不能先搞出坐标,直接算角度就行了,不然会卡精度/px flag:计 ...
- 退役II次后做题记录
退役II次后做题记录 感觉没啥好更的,咕. atcoder1219 历史研究 回滚莫队. [六省联考2017]组合数问题 我是傻逼 按照组合意义等价于\(nk\)个物品,选的物品\(\mod k\) ...
- BJOI做题记录
BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...
- FJOI2017前做题记录
FJOI2017前做题记录 2017-04-15 [ZJOI2017] 树状数组 问题转化后,变成区间随机将一个数异或一,询问两个位置的值相等的概率.(注意特判询问有一个区间的左端点为1的情况,因为题 ...
- HDU 1251 统计难题 (Trie树模板题)
题目链接:点击打开链接 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单 ...
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- UOJ 做题记录
UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...
- HDU 1251 Trie树模板题
1.HDU 1251 统计难题 Trie树模板题,或者map 2.总结:用C++过了,G++就爆内存.. 题意:查找给定前缀的单词数量. #include<iostream> #incl ...
随机推荐
- Kubernetes 轻松管理资源
资源管理介绍 在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes. kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务,所谓的部署 ...
- 玩转云端 | 网络也i人?咋变显眼包?天翼云AccessOne边缘接入来了!
你是具有"社牛"属性的"e人" 还是"社恐"属性的"i人"? 在年轻群体中火起来的 "MBTI人格测试&quo ...
- Linux docker 的安装及使用
Docker 有两个版本: 社区版(Community Edition,缩写为 CE) 企业版(Enterprise Edition,缩写为 EE) 检查环境 # 系统内核需要 3.10 以上 una ...
- HTML布局常用标签——div和span
HTML布局常用标签--div和span 在HTML的世界里,div和span是两位不可或缺的老朋友,它们虽然看似简单,却在网页布局和样式设计中发挥着举足轻重的作用.今天,我们就来聊聊这两位" ...
- 流程控制之do while循环
语法 do { //代码语句}while(布尔表达式): 与while的区别 while是先判断再执行,do while是先执行再判断 循环体至少会被执行一次 实例1: package com. ...
- C51二进制数输入宏
在C语言中有十进制,十六进制,八进制;没有二进制的定义,在C51中使用十六进制表示有时不太直观,下面介绍几种方法表示二进制[均来自网络] 方法一 #define _BIN(a,b,c,d,e,f,g, ...
- java推送企业微信消息
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcl ...
- 如何用爱思助手给苹果iPhone手机免越狱修改虚拟定位教程
使用爱思助手修改定位的方法: 1.在电脑上下载安装 爱思助手 客户端,并更新到最新版,用数据线将苹果移动设备连接到电脑. 2.连接成功后,依次打开爱思助手"工具箱 - 虚拟定位". ...
- web站点常见漏洞及解决方法
1.PHP Web表单哈希冲突拒绝服务漏洞 漏洞分析:PHP 5.3.9之前版本在计算表单参数哈希值的实现上存在拒绝服务漏洞,该漏洞源于未提前限制哈希冲突.攻击者可利用该漏洞通过发送小量的特制webf ...
- 【目标检测】一、初始的R-CNN与SVM
1.流程 为什么要用SVM而不是CNN最后一层的softmax? 取什么模型必然是有标准衡量,这个流程取得是书上[4]写的,作者说他得实验证明SVM比FC的mAP要高,所以我流程暂且这样画了. R-C ...