首页 > 其他分享 >「Day-2 提高笔记-字典树」

「Day-2 提高笔记-字典树」

时间:2024-10-16 22:32:37浏览次数:1  
标签:前缀 int 笔记 Day MAXN 向下 节点 字典

字典树

字典树是什么?

理论知识

  1. 插入操作

我们在插入的时候,先从根节点去向下遍历。对于字符串 \(S\) 的一位 \(S_i\)。

  • 如果发现其在字典树中当前节点下有这个字符 \(S_i\),则继续向下,在向下的过程中每次给当前节点的次数加 \(1\),记录字符串前缀数量。
  • 若无这个字符,则开辟一个新的节点,记录节点编号,继续向下。
  1. 查询前缀数量

我们在查询前缀的时候,先从根节点去向下遍历。对于字符串 \(S\) 的一位 \(S_i\)。

  • 若在字典树当前节点下没有 \(S_i\),则证明没有以该前缀为开头的单词。
  • 否则就继续向下,直到 \(S_n\),最后返回该节点数下的前缀数量。

时间复杂度

对于一个长度为 \(n\) 字符串。
\(Insert\) 和 \(query\) 的时间复杂度都是 \(O(n)\)。

代码实现

P8306 【模板】字典树

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 3e6 + 5;
int T;
int n,q;
char s[MAXN];
int ch[MAXN][100],cnt[MAXN],id = 0;

int got(char c){
	if(c >= 'A' && c <= 'Z') return c - 'A';
	if(c >= 'a' && c <= 'z') return c - 'a' + 26;
	return c - '0' + 52;
}

void Insert(char *s){
	int now = 0;
	for(int i = 0;s[i];i ++){
		int v = got(s[i]);
		if(!ch[now][v]){
			ch[now][v] = ++ id;
		}
		now = ch[now][v];
		cnt[now] ++; 
	}
	return;
}

int query(char *s){
	int now = 0;
	for(int i = 0;s[i];i ++){
		int v = got(s[i]);
		if(!ch[now][v]) return 0;
		now = ch[now][v];
	}
	return cnt[now];
}

void Clear(){
    memset(ch, 0, sizeof(ch[0]) * (id + 1));
    memset(cnt, 0, sizeof(cnt[0]) * (id + 1));
    id = 0;
}

signed main(){
	scanf("%d",&T);
	while(T --){
		scanf("%d%d",&n,&q);
		for(int i = 1;i <= n;i ++){
			scanf("%s",s);
			Insert(s);
		}
		for(int i = 1;i <= q;i ++){
			scanf("%s",s);
			cout << query(s) << '\n';
		}
		Clear();
	}
	return 0;
}

标签:前缀,int,笔记,Day,MAXN,向下,节点,字典
From: https://www.cnblogs.com/To-Carpe-Diem/p/18471072

相关文章

  • 机器学习篇-day08-聚类Kmeans算法
    一.聚类算法简介概念无监督学习算法根据样本之间的相似性,将样本划分到不同的类别中;不同的相似度计算方法,会得到不同的聚类结果,常用的相似度计算方法有欧式距离法。聚类算法的目的是在没有先验知识的情况下,自动发现数据集中的内在结构和模式。使用不同的聚类准则,产生的......
  • STM32学习笔记—USART串口
    USART串口协议通信接口通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统通信协议:制定通信的规则,通信双方按照协议规则进行数据收发全双工:通信双方能够同时进行双向通信。全双工有两根通信线。半双工:数据可以沿两个方向传送,但同一时刻一个信道只允许单方向传送。I......
  • 嵌入式学习-IO进程-Day03
    嵌入式学习-IO进程-Day03IO进程获取文件属性(stat)库库的概念库的分类静态库的制作动态库的制作进程进程和程序的区别进程的特点进程三段进程的类型进程的运行状态进程状态转换图(重点)进程的函数接口创建进程forkfork函数创建的子进程的特点IO进程获取文件......
  • RabbitMQ系列学习笔记(三)--工作队列模式
    文章目录一、工作队列模式原理二、工作队列模式实战1、抽取工具类2、消费者代码3、生产者代码4、查看运行结果本文参考尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmqRabbitMQ详解Centos7环境安装Erlang、RabbitMQ详细过程(配图)一、工作队列模式原理与......
  • 代码随想录算法训练营day17| 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜
    学习资料:https://programmercarl.com/0654.最大二叉树.html#算法公开课用前序遍历构造二叉树二叉搜索树的特点,其左节点的值<每个节点的值<其右节点的值,且根节点的值大于它的左子树的所有节点的值,小于它右子树的所有节点的值,其他同理。二叉搜索树的搜索和验证时不关心遍历顺序,因......
  • 第2课笔记 linux系统指令
    测试分类linux虚拟机搭建linux命令:一、linux介绍1、Linux是一个免费、开源的操作系统,能多用户、多任务、支持多线程和多CPU的操作系统,相对windows更加稳定,在unix系统的基础上开发的系统;注解:(1)免费:不要钱(2)源代码公开(3)多用户:可以在不同用户操作(4)多任务:同时执行多个任务......
  • StarSilk 题单笔记-2000
    LinkLexicographicallyLargest首先,第\(i\)位数字最大贡献是\(a_i+i\),并且可以全部取到(倒着丢数即可)。但因为\(S\)是不可重集,为了最大化字典序,我们需要把重复的同一个数字\(x\)变成\(x-1,x-2,x-3\dots\)。这很简单,我们把每个\(a_i+i\)丢进一个数组\(b\)里排倒序,......
  • java_day13_ArrayList、Vector、LinkedList、泛型
    一、ArrayListCollection[接口]:List[接口]:元素有序,可以发生重复,有索引的概念ArrayList[具体的子类]:底层数据结构是数组,查询快,增删慢,线程不安全,效率高。Set[接口]:元素无序且唯一,没有索引代码案例publicclassArrayListDemo1{publicstaticv......
  • Java 初学 day12
    java12集合1、Collection到目前位置,我们学习过哪些可以存储元素的容器1、数组优点:不同的数组可以存储不同数据类型的元素缺点:长度不可变2、StringBuffer|StringBuilder优点:长度可以跟随元素的数量而改变缺点:里面的元素只有一种字符数据类型我们今后会......
  • 2024/10/16 日 日志 --》关于Mysql的中DQL的初步学习笔记与整理
    在前几天已经进行了Mysql的初步准备和学习,接下来我将继续向后推进。以下为课程学习整理,方便记忆和复习。点击查看代码-------DQL----基础查询--1.查询多个字段--SELECT字段列表form表名 ;--selcet*form表名;--查询所有数据--2.去除重复记录--selectdist......