字典树入门

news2025/3/3 4:42:00

 

//本题是一道字典树的模板题
//字典树是一种高效率存储多个字符串的数据结构
//其每个结点的权值代表以该结点结尾的字符串的数量,每条边存储一个字符
//从根结点开始,按某一路径遍历到某一结点,即得到一种字符串,其个数等于当前结点存储的数值
//如从根结点开始,依次走过'a''b''c'三条边到达9号结点,9号结点保存的数字是3
//则得到字符串"abc",其数量为3个 
#include <bits/stdc++.h>

using namespace std;

const int N=2e6+100;

int nex[N][27];//nex[i][0]表示从结点i出发,边为'a'的下一个结点地址(假设字符串全由小写字母构成)
//如1号结点与2号结点间存在一条记录字母'a'的边,则nex[1]['a'-'a']=2 
//如8号结点与9号结点间存在一条记录字母'c'的边,则nex[8]['c'-'a']=9 
int cnt[N];//cnt[i]表示以结点i结尾的字符串的数量,即每个结点的权值 
int idx=2;//用于动态开点,初始时只有一个根结点1 

void insert(char *S)//在字典树中插入字符串S的信息 
{
    int x=1;//x表示结点编号,初始从根结点(1号)开始 
    for(int i=0;S[i]!='\0';i++)//遍历字符串S 
    {
        //先检查x是否存在S[i]的边 
        if(nex[x][S[i]-'a']==0)//从结点x出发,目前还没有记录当前字母的边 
        {
            nex[x][S[i]-'a']=idx++;//则新建一个边记录之,同时动态开点 
        }
        x=nex[x][S[i]-'a'];//到达下一个结点编号
    }    
    //cnt[x]++;
    //最终x到达字符串末尾字符对应的结点上,其计数值加1 
}

bool check(char *T)//在字典树中查找字符串T(计算出现的次数)
{
    int x=1;//x表示结点编号,初始从根结点(1号)开始 
    for(int i=0;T[i]!='\0';i++)//遍历字符串T 
    {
        x=nex[x][T[i]-'a'];//根据当前字符,x不断向下追溯,最终到达结尾
        //若不存在这个字符(记录这个字符的边),则x=0,后续x将一直为0 
    }    
    //return cnt[x];//返回字符串T出现的次数,即结尾字符对应的结点所记录的权值 
    return x;//本题返回x即可,只需判断x是否为0 
}

int main()
{
    int n,m;
    cin>>n>>m;
    while(n--)//N个字符串 
    {
        char S[N];
        cin>>S;
        insert(S);//每输入一个字符串,就将其信息插入字典树 
    }    
    while(m--)//M个询问 
    {
        char T[N];
        cin>>T;
        if(check(T))cout<<"Y"<<endl;//在字典树中找到T,输出Y 
        else cout<<"N"<<endl;//没找到,输出N 
    }
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+9;
int nex[N][26];
int cnt[N];
int idx=2;

void insert(char s[]){
    int x=1;
    for(int i=0;s[i]!='\0';i++){
      if(!nex[x][s[i]-'a'])nex[x][s[i]-'a']=idx++;
      x=nex[x][s[i]-'a'];
    }
}
bool check(char *T){
  int x=1;
  for(int i=0;T[i]!='\0';i++){
  x=nex[x][T[i]-'a'];
  if(x==0)return 0;
  }
  return 1;
}
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++){
        char s[N];cin>>s;
        insert(s);
    }
    for(int i=1;i<=m;i++){
        char s[N];cin>>s;
        cout<<(check(s)?"Y":"N")<<"\n";
    }
    return 0;
}

 

 

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+6;
int nex[N][27];//nex[i][a]=j表示从结点i到结点j嗲表的是字母a
int cnt[N];
int idx=2;
void insert(char s[]){
  int x=1;//根结点 
  for(int i=0;s[i]!='\0';i++){
    cnt[x]++;
    if(!nex[x][s[i]-'a'])nex[x][s[i]-'a']=idx++;
    x=nex[x][s[i]-'a'];
  }
  cnt[x]++;
}
int check(char t[]){
  int x=1;
  for(int i=0;t[i]!='\0';i++){
    x=nex[x][t[i]-'a'];
  }
  return cnt[x];
}
int main(){
  int n,m;cin>>n>>m;
  for(int i=1;i<=n;i++){
    char s[N];cin>>s;
    insert(s);
  }
  for(int i=1;i<=m;i++){
    char t[N];cin>>t;
    cout<<check(t)<<'\n';
  }
  return 0;
}
//本题是一道比较简单的字典树的应用题 
#include <bits/stdc++.h>

using namespace std;

const int maxn=1e5+100;

int nex[maxn][27];//nex[x][0]表示从第x个结点开始,边为'a'的下一个结点的地址(全为小写字母) 
int cnt[maxn];//cnt[i]存储以第i个结点结尾的前缀的数量 
int idx=2;//用于动态开点 

void Insert(string s)//将字符串s插入字典树中 
{
    int x=1;//初始从根结点(1号)开始 
    for(int i=0;i<s.size();i++)//遍历字符串 
    {
        cnt[x]++;//以当前字母结尾的前缀数量+1 
        if(nex[x][s[i]-'a']==0)//若该字母未记录过(不存在对应的边) 
        {
            nex[x][s[i]-'a']=idx++;//则动态开点并记录之 
        }    
        x=nex[x][s[i]-'a'];//继续向下追溯 
    }    
    cnt[x]++;//以最后一个字符结尾的前缀的数量+1 
}

int Search(string s)//在字典树中查找字符串s,并返回匹配成功的次数 
{
    int x=1;//初始从根结点(1号)开始 
    for(int i=0;i<s.size();i++)//遍历字符串s 
    {
        x=nex[x][s[i]-'a'];    //不断向下追溯直到结尾 
    }    
    return cnt[x];//返回结尾结点记录的前缀数量 
}

int main()
{
    int N,M;
    cin>>N>>M;    
    while(N--)//输入N组字符串并插入字典树 
    {
        string s;
        cin>>s;
        Insert(s);
    }
    while(M--)//M轮询问 
    {
        string s;
        cin>>s;
        cout<<Search(s)<<endl;//在字典树中查找匹配成功的次数并输出 
    }
    return 0;
}

 

 

 

//本题考察字典树的扩展应用
//其具体算法仍是字典树的插入与查询
//需要注意的是当前字符串不能与自己匹配,
 //由于插入与删除的本质相同,只是cnt数组对应位置的增加或减小,故只需改写插入函数即可 
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;

string str[maxn];//存储原始字符串组 
int nex[maxn][27];//nex[x][0]表示从第x个结点出发,边为'a'的下一个结点地址 
int cnt[maxn];//cnt[i]表示以第i个结点结尾的前缀的数量 
int idx=2;//用于动态开点 

void Insert(string s,int tag)//将字符串s插入字典树中,或将其从字典树中删除
//若传入tag=1,则为插入;若传入tag=-1,则为删除
//插入与删除的本质是令对应的cnt[x]+1或-1 
{
    int x=1;//初始从根结点(1号)开始 
    for(int i=0;i<s.size();i++)//遍历字符串s 
    {
        cnt[x]+=tag;//对每个字符,以该字符结尾的前缀数量均+1/-1 
        if(nex[x][s[i]-'a']==0)//若该字符(存储该字符的边)未被记录 
        {
            nex[x][s[i]-'a']=idx++;//则动态开点并记录之 
        }
        x=nex[x][s[i]-'a'];//继续向下追溯 
    }        
    cnt[x]+=tag;//结尾字符对应的前缀数量+1/-1 
}

int Search(string s)//在字典树中查找与s最接近的字符串,并返回匹配的最长前缀的长度 
{
    int x=1;//初始从根结点(1号)开始 
    int ans=0;//记录匹配的最长前缀的长度 
    for(int i=0;i<s.size();i++)//遍历字符串 
    {
        if(nex[x][s[i]-'a']==0)//已经无法再匹配(不存在记录当前字符的边)
        {
            return ans;//返回之前累计的长度 
        }    
        x=nex[x][s[i]-'a'];//若能继续匹配,则继续向下追溯 
        if(cnt[x]==0)return ans;//已经不存在以x结点结尾的前缀,返回之前累计的长度
        //注意以上这句不可省略,因为在删除操作中只是减少了字符串出现的次数,并没有删除之前记录的字符 
        ans++;//计数值加1,重复上述操作 
    }    
    return ans;//最终返回ans 
}

int main()
{
    int N;
    cin>>N;
    for(int i=0;i<N;i++)//输入N个字符串 
    {
        cin>>str[i];
        Insert(str[i],1);//插入 
    }
    for(int i=0;i<N;i++)//N组查询 
    {
        Insert(str[i],-1);//先将当前字符串删除 
        cout<<Search(str[i])<<'\n';//查询匹配的最长前缀的长度并输出 
        Insert(str[i],1);//将当前字符串重新插入以恢复字典树 
    }
    return 0;
}

 

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

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

相关文章

【iOS ARKit】ARWorldMap

ARWorldMap 用于存储 ARSession 检测扫描到的空间信息数据&#xff0c;包括地标&#xff08;Landmark&#xff09;、特征点&#xff08;Feature Point&#xff09;、平面&#xff08;Plane&#xff09;等&#xff0c;以及使用者的操作信息&#xff0c;如使用者添加的 ARAnchor …

【Vue】组件通信组件通信

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;JVM ⛺️稳中求进&#xff0c;晒太阳 组件通信 组件通信&#xff0c;就是指组件与组件之间的数据传递 组件的数据是独立的&#xff0c;无法直接访问其他组件的数据想用其他组件的数据--&…

【深度学习】Pytorch教程(十三):PyTorch数据结构:5、张量的梯度计算:变量(Variable)、自动微分、计算图及其可视化

文章目录 一、前言二、实验环境三、PyTorch数据结构1、Tensor&#xff08;张量&#xff09;1. 维度&#xff08;Dimensions&#xff09;2. 数据类型&#xff08;Data Types&#xff09;3. GPU加速&#xff08;GPU Acceleration&#xff09; 2、张量的数学运算1. 向量运算2. 矩阵…

景联文科技:引领战场数据标注服务,赋能态势感知升级

自21世纪初&#xff0c;信息化战争使战场环境变得更为复杂和难以预测&#xff0c;持续涌入的海量、多样化、多来源和高维度数据&#xff0c;加大了指挥员的认知负担&#xff0c;使其需要具备更强的数据处理能力。 同时&#xff0c;计算机技术和人工智能技术的飞速发展&#xff…

EMQX Enterprise 5.5 发布:新增 Elasticsearch 数据集成

EMQX Enterprise 5.5.0 版本已正式发布&#xff01; 在这个版本中&#xff0c;我们引入了一系列新的功能和改进&#xff0c;包括对 Elasticsearch 的集成、Apache IoTDB 和 OpenTSDB 数据集成优化、授权缓存支持排除主题等功能。此外&#xff0c;新版本还进行了多项改进以及 B…

Gemma谷歌(google)开源大模型微调实战(fintune gemma-2b)

Gemma-SFT Gemma-SFT(谷歌, Google), gemma-2b/gemma-7b微调(transformers)/LORA(peft)/推理 项目地址 https://github.com/yongzhuo/gemma-sft全部weights要用fp32/tf32, 使用fp16微调十几或几十的步数后大概率lossnan;(即便layer-norm是fp32也不行, LLaMA就没有这个问题, …

SpringBoot/Java中OCR实现,集成Tess4J实现图片文字识别

场景 Tesseract Tesseract是一个开源的光学字符识别&#xff08;OCR&#xff09;引擎&#xff0c;它可以将图像中的文字转换为计算机可读的文本。 支持多种语言和书面语言&#xff0c;并且可以在命令行中执行。它是一个流行的开源OCR工具&#xff0c;可以在许多不同的操作系…

【Vue3】插槽使用和animate使用

插槽使用 插槽slot匿名插槽具名插槽插槽作用域简写 动态插槽transition动画组件自定义过渡class类名如何使用animate动画库组件动画生命周期appear transition- group过渡列表 插槽slot 插槽就是子组件中提供给父组件使用的一个占位符父组件可以在这个占位符智能填充任何模板代…

pytest-配置项目不同环境URL

pytest自动化中&#xff0c;在不同环境进行测试&#xff0c;可以将项目中的url单独抽取出来&#xff0c;通过pytest.ini配置文件实现&#xff08;类似postman中的“Environments”&#xff09; 使用步骤&#xff1a; 1&#xff09;安装pytest-base-url插件 pytest-base-url …

【Flink精讲】Flink状态及Checkpoint调优

RocksDB大状态调优 RocksDB 是基于 LSM Tree 实现的&#xff08;类似 HBase&#xff09; &#xff0c;写数据都是先缓存到内存中&#xff0c; 所以 RocksDB 的写请求效率比较高。 RocksDB 使用内存结合磁盘的方式来存储数据&#xff0c;每 次获取数据时&#xff0c;先从内存中 …

Mac下载安装配置运行MySQL

一、打开官网 MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 1、根据自己的电脑版本下载相对应的MySQL版本&#xff0c;Mac分为ARM和X86两个不同的架构 ​ 不知道自己电脑是ARM还是X86的&#xff0c;如下操作进行查询 uname -a 我的电脑是…

2024年Apache DolphinScheduler RoadMap:引领开源调度系统的未来

非常欢迎大家来到Apache DolphinScheduler社区&#xff01;随着开源技术在全球范围内的快速发展&#xff0c;社区的贡献者 “同仁” 一直致力于构建一个强大而活跃的开源调度系统社区&#xff0c;为用户提供高效、可靠的任务调度和工作流管理解决方案。 在过去的一段时间里&…

代码随想录|学习工具分享

工具分享 画图 https://excalidraw.com/ 大家平时刷题可以用这个网站画草稿图帮助理解&#xff01;如果看题解很蒙或者思路不清晰的时候&#xff0c;跟着程序处理流程画一个图&#xff0c;90%的情况下都可以解决问题&#xff01; 数据结构可视化 https://www.cs.usfca.edu/…

【Java设计模式】一、工厂模式、建造者模式、原型设计模式

文章目录 1、简单工厂模式2、工厂方法模式3、抽象工厂模式4、建造者模式5、原型设计模式 设计模式即总结出来的一些最佳实现。23种设计模式可分为三大类&#xff1a; 创建型模式&#xff1a;隐藏了创建对象的过程&#xff0c;通过逻辑方法进行创建对象&#xff0c;而不是直接n…

逆序或者正序打印一个数的每一位数,递归实现(C语言)

从键盘上输入一个不多于5位&#xff08;包括5位&#xff09;的正整数&#xff0c;要求 &#xff08;1&#xff09;求出它是几位数&#xff1b;&#xff08;2&#xff09;分别输出每一位数字&#xff08;3&#xff09;按逆序输出各位数字 &#xff08;1&#xff09;求出它是几位…

Linux浅学笔记04

目录 Linux实用操作 Linux系统下载软件 yum命令 apt systemctl命令 ln命令 日期和时区 IP地址 主机名 网络传输-下载和网络请求 ping命令 wget命令 curl命令 网络传输-端口 进程 ps 命令 关闭进程命令&#xff1a; 主机状态监控命令 磁盘信息监控&#xff1a…

【MQ05】异常消息处理

异常消息处理 上节课我们已经学习到了消息的持久化和确认相关的内容。但是&#xff0c;光有这些还不行&#xff0c;如果我们的消费者出现问题了&#xff0c;无法确认&#xff0c;或者直接报错产生异常了&#xff0c;这些消息要怎么处理呢&#xff1f;直接丢弃&#xff1f;这就是…

深入理解计算机系统学习笔记

第三章 程序的机器级表示 3.2.1 机器级代码 对于机器级编程来说&#xff0c;其中两种抽象尤为重要。第一种是由捍令集体系结构或指令集架构&#xff08;Instruction Set Architecture, ISA)来定义机器级程序的 格式和行为&#xff0c;它定义了处理器状态、指令的格式&#xf…

在Ubuntu上为ARM 8处理器安装Python 3.10.4虚拟环境指南

在Ubuntu上为ARM 8处理器安装Python 3.10.4虚拟环境指南 安装Anaconda或Miniconda&#xff1a; 首先&#xff0c;您需要从官方网站下载适用于ARM架构的Anaconda或Miniconda安装包。下载完成后&#xff0c;在终端中使用bash Anaconda3-2019.10-Linux-armv8.sh&#xff08;文件…

将仓库A中的部分提交迁移到仓库B中

结论&#xff1a; 使用git format-patchgit am即可实现 使用场景&#xff1a; 例如仓库A这里有5个提交记录&#xff0c;commitid1, commitid2, commitid3, commitid4&#xff0c;commitid5 仓库B想用仓库A中提交的代码&#xff0c;手动改比较慢&#xff0c;当改动较多的时候…