Trie字符串统计-java

Trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。

目录

前言☀

一、Trie字符串统计☀

二、算法思路☀

1.Trie树定义🌙

2.变量解释🌙

3.插入操作🌙

4.Trie树查找操作 🌙

三、代码如下☀

1.代码如下:🌙

2.读入数据🌙

3.代码运行结果🌙

 4.运行结果解释🌙

总结☀


前言☀

Trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Trie字符串统计☀

维护一个字符串集合,支持两种操作:

  1. I x 向集合中插入一个字符串 x;
  2. Q x 询问一个字符串在集合中出现了多少次。

共有 N 个操作,所有输入的字符串总长度不超过 100000,字符串仅包含小写英文字母。

输入格式

第一行包含整数 N,表示操作数。

接下来 N行,每行包含一个操作指令,指令为 I x 或 Q x 中的一种。

输出格式

对于每个询问指令 Q x,都要输出一个整数作为结果,表示 x 在集合中出现的次数。

每个结果占一行。

数据范围

1≤N≤2∗10000

二、算法思路☀

1.Trie树定义🌙

图1.1Trie树示例 

 Trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。

Trie树是用来高效的存储和查找字符串的集合的数据结构。

基本性质:

1、根节点不包含字符,除根节点意外每个节点只包含一个字符。

2、从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。

3、每个节点的所有子节点包含的字符串不相同。

图1.1中我们用trie树存储了abcdef、abdef、aced、bcdf、bcff、cdaa、bcdc字符串。

我们会在一个单词的结尾来做一个标记,来表示到这里有一个完整的单词。

2.变量解释🌙

我们引入整型变量N为100010,用来表示树深最高100000个结;然后有因为字符串中只有小写字母,那么一个结点最多有26个分支,那么我们用一个二维整型数组son来存储,共有N行26列;用一维整型数组cnt来存储以某节点结束的字符串的个数,同时起到字符串结束的作用,引入一个整型变量index,初始化为0,用来表示空节点。

3.插入操作🌙

插入操作我们按照一个字符串的字母顺序第一个字符是根节点的分支,然后下一个字母是上一个字母的分支,直到单词的结束;遇到相同前缀的单词在相同单词的前缀后的不同分支接着串连字母,当然每个单词的最后一个字母都会有一个结束标志。具体模拟过程可以看图1.1.

图3.1模拟过程

对于一个字符串str,获取对应的字符数组arr,建立一个整型变量p初始化为0,相当于一个指针变量指向当前节点,我们遍历每个字符arr[i] ,然后用u = arr[i] - 'a',将每个字符转换成数字关系,当该字符未被放入Trie树中时即(son[p][u] == 0),将son[p][u] = ++index;意思是当该节点不存在的时候,我们创建出来,然后数组中的值是下一个节点的位置;然后将当前节点的指针p指向下一个节点的位置即 p = son[p][u];当该字符串的所有字符遍历结束后,将cnt[p]++;此时p的值就是当前节点的位置,还因为index的值是随着我们没新创建一个节点增加的,是唯一的,它可以用来表示字符串结束的标识。

    public static void insert(String str){char[] arr = str.toCharArray();int p = 0;for(int i = 0;i < arr.length;i++){int u = arr[i] - 'a';//字符不在Trie树中if(son[p][u] == 0){//创建一个节点,数组中的值为下一个节点的位置son[p][u] = ++index;}//使指针指向下一个节点的位置p = son[p][u];}//结束时标记,记录以此节点为结尾的字符串的个数cnt[p]++;}

4.Trie树查找操作 🌙

我们还用图1.1来看,当我们查找字符串acf的时候。从root-> a -> c - > e,此时a的后面没有f,就说明Trie树中不存在acf字符串;当我们字符串cda的时候,从root - > c - > d - > a,但是字符a没有单词结束标志,那么说明Trie树中同样也没有字符串cda。

我们传入一个字符串str,然后利用对应的字符数组arr,建立一个整型变量p初始化为0,相当于一个指针变量指向当前节点,我们遍历每个字符arr[i] ,然后用u = arr[i] - 'a',将每个字符转换成数字关系,当我们发现该字符不在Trie树中时即son[p][u] == 0,即该字符串不存在直接返回0即可;当该字符存在,那么就将p指针指向该节点的下一个节点位置 p = son[p][u],将该字符数组遍历完毕后,最后返回该字符串的个数就是以最后一个节点的位置对应的cnt数组中的值即cnt[p]。

    public static int query(String str){char[] arr = str.toCharArray();int p = 0;for(int i = 0;i < arr.length;i++){int u = arr[i] - 'a';//不存在if(son[p][u] == 0){return 0;}p = son[p][u];}//返回字符串出现的次数return cnt[p];}

三、代码如下☀

1.代码如下:🌙


import java.io.*;
import java.util.*;public class Trie字符串统计 {static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//一个字符串最多100000个字符static int N = 100010;//存储子节点后面的分支,因为只有小写字母,故只有26个分支static int[][] son = new int[N][26];//存储以某节点结束的字符串的个数,同时起到字符串结束的标志作用static int[] cnt = new int[N];//下标是0的点既是根节点static int index = 0;public static void main(String[] args) throws Exception {Scanner sc = new Scanner(br);int m = sc.nextInt();while (m-- > 0){String cmd = sc.next();String str = sc.next();if (cmd.equals("I")){insert(str);}else if (cmd.equals("Q")){pw.println(query(str));}}pw.flush();}public static void insert(String str){char[] arr = str.toCharArray();int p = 0;for(int i = 0;i < arr.length;i++){int u = arr[i] - 'a';//字符不在Trie树中if(son[p][u] == 0){//创建一个节点,数组中的值为下一个节点的位置son[p][u] = ++index;}//使指针指向下一个节点的位置p = son[p][u];}//结束时标记,记录以此节点为结尾的字符串的个数cnt[p]++;}public static int query(String str){char[] arr = str.toCharArray();int p = 0;for(int i = 0;i < arr.length;i++){int u = arr[i] - 'a';//不存在if(son[p][u] == 0){return 0;}p = son[p][u];}//返回字符串出现的次数return cnt[p];}
}

2.读入数据🌙

5
I abc
Q abc
Q ab
I ab
Q ab

3.代码运行结果🌙

1
0
1

 4.运行结果解释🌙

图4.1 

插入abc后查询abc为1;查询ab不存在为0; 插入ab;查询ab存在为1。


总结☀

主要了解Trie树的构造性质后,直到如何插入字符串,如何查询字符串;了解代码中各个变量的含义,直到每一步是干什么,可以跟着图示自己手动模拟一下,体验一下过程,加深自己的理解。

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

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

相关文章

【算法】位运算算法——丢失的数字

题解&#xff1a;丢失的数字(位运算算法) 目录 1.题目2.题解3.位运算异或4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 哈希数组查漏高斯求和排序位运算异或… 3.位运算异或 class Solution { public:int missingNumber(vector<int>& nums) {int ret 0;for…

动态规划之买卖股票大集合

目录 引言 1.只能进行一次买卖股票&#xff08;最多只能买一股股票&#xff09; 2.可以进行多次股票买卖&#xff0c;且没有手续费&#xff08;最多只能买一股股票&#xff09; 3.可以进行多次股票买卖&#xff0c;但是有冷冻期&#xff0c;无手续费&#xff08;最多只能买一…

电脑卡顿---WINDOWS任何关闭应用开机自启动

打开windows11的控制面板&#xff0c;点击应用&#xff0c;点击启动 如下图圈出来的地方就是开机自启动的开关按键。

Android 11 Audio音频系统配置文件解析

在AudioPolicyService的启动过程中&#xff0c;会去创建AudioPolicyManager对象&#xff0c;进而去解析配置文件 //frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientIn…

如何在生产环境中以非 Root 用户启动 Kafka

目录 如何在生产环境中以非 Root 用户启动 Kafka1. 创建 Kafka 用户2. 设置目录权限3. 配置 systemd 服务文件4. 启动和启用 Kafka 服务5. 验证 Kafka 服务经验总结 为了在生产环境中以非 root 用户&#xff08;如 kafka 用户&#xff09;启动 Kafka&#xff0c;您需要确保 Ka…

【软件测试】bug篇|软件测试的生命周期|描述bug的要素|bug的级别|bug的生命周期|高频面试题:与开发产⽣争执怎么处理

目录 一、软件测试的⽣命周期 二、BUG 2.1 bug的概念 2.2 描述bug的要素 2.3 bug级别 2.4 bug的⽣命周期 &#x1f4a1;2.5 与开发产⽣争执怎么办&#xff08;⾼频考题&#xff09; &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

Unity实现首行缩进两个字符

效果 在Unity中如果想实现首行缩进两个字符&#xff0c;你会发现按空格是没法实现的。 实现原理&#xff1a;用空白的透明的字替代原来的位置。 代码&#xff1a; <color#FFFFFF00>XXX</color> 赶紧去试试吧&#xff01;

CASS11自定义宗地图框

1、找到CASS11的安装路径&#xff0c;找到如下文件夹&#xff1a; 2、打开【report】文件夹&#xff0c;如下&#xff1a; 3、打开其中一个压缩包&#xff0c;如【标准宗地图】压缩包&#xff0c;结果如下&#xff1a; 4、打开后&#xff0c;将其另存为到桌面&#xff0c;随后关…

新书推荐:7.5 goto、break、continue语句

本节必须掌握的知识点&#xff1a; 示例二十六 代码分析 汇编解析 示例二十七 代码分析 汇编解析 7.5.1 示例二十六 ■goto语句&#xff1a;无条件转移语句。 语法格式&#xff1a; goto label; label : 代码; ●语法解析&#xff1a; 执行到goto语句时&#xff0c;则无…

释放 OSINT 的力量:在线调查综合指南

开源情报 (OSINT) 是从公开信息中提取有价值见解的艺术。无论您是网络安全专业人士、道德黑客还是情报分析师&#xff0c;OSINT 都能为您提供先进的技术&#xff0c;帮助您筛选海量的数字数据&#xff0c;发现隐藏的真相。 在本文中&#xff0c;我们将深入研究大量的OSINT 资源…

项目十三:搜狗——python爬虫实战案例

根据文章项目十二&#xff1a;简单的python基础爬虫训练-CSDN博客的简单应用&#xff0c;这一次来升级我们的技术&#xff0c;那么继续往下看&#xff0c;希望对技术有好运。 还是老样子&#xff0c;按流程走&#xff0c;一条龙服务&#xff0c;嘿嘿。 第一步&#xff1a;导入…

12.2 通道-阻塞与流程控制、通道型函数、退出通道

阻塞与流程控制 通常在并发程序中要尽力避免阻塞式操作&#xff0c;但有时又需要让代码暂时处于阻塞状态&#xff0c;以等待某种条件、信号或数据&#xff0c;然后再继续运行。 对于无缓冲通道&#xff0c;试图从无人写入的通道中读取&#xff0c;或者向无人读取的通道中写入…

【Sql Server】随机查询一条表记录,并重重温回顾下自定义函数的封装和使用

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言随机查询语…

MongoDB数据库(10亿条数据)清理策略: 自动化过期数据删除实战

1、引言 随着应用程序和业务数据的持续增长&#xff0c;有效地管理数据库存储空间成为维护系统性能的关键。在MongoDB这类NoSQL数据库中&#xff0c;定期清理过期数据变得尤为重要&#xff0c;这不仅能释放宝贵的存储资源&#xff0c;还能优化查询性能&#xff0c;确保数据库运…

5,串口编程---实现简单的用串口发送接收数据

单片机通过串口向PC机发送数据 PC机通过串口接收单片机发过来的数据 1.UART和USART的区别&#xff1a; USART支持同步通信方式,可以通过外部时钟信号进行同步传输,而UART仅支持异步通信方式 本开发板STM32F103ZET6有5个串口&#xff0c;用串口1作调试串口&#xff0c;因为串…

让AI学相机对焦: Learning to AutoFocus

前言 分析来自谷歌发表在 CVPR 2020 上的论文 Learning to Autofocus &#xff1a;https://arxiv.org/pdf/2004.12260 目前网上对这篇论文的分析较少&#xff0c;有的分析并没有指出关键点&#xff0c;如&#xff1a;论文解读&#xff1a; Learning to AutoFocus-CSDN博客&am…

spring常用知识点

1、拦截器和过滤器区别 1. 原理不同&#xff1a; 拦截器是基于java的反射机制&#xff0c;而过滤器采用责任链模式是基于函数回调的。 2. 使用范围不同&#xff1a; 过滤器Filter的使用依赖于Tomcat等容器&#xff0c;导致它只能在web程序中使用 拦截器是一个Sping组件&am…

jQuery 常用API

一、jQuery 选择器 1、jQuery 基础选择器 原生JS获取元素方式很多&#xff0c;很杂&#xff0c;而且兼容性情况不一致&#xff0c;因此jQuery给我们做了封装&#xff0c;使获取元素统一标准 2、jQuery 层级选择器 3、隐式迭代 遍历内部 DOM 元素&#xff08;伪数组形式存储&am…

存储+调优:存储-IP-SAN-EXTENSION

存储调优&#xff1a;存储-IP-SAN-EXTENSION 文件系统的锁标记 GFS&#xff08;锁表空间&#xff09; ----------- ------------ ------------- 节点 | ndoe1 | | node2 | | node3 | ---------- ------…

STM32建立工程问题汇总

老版本MDK&#xff0c;例如MDK4 工程内容如下&#xff1a; User文件夹中存放main.c文件&#xff0c;用户中断服务函数&#xff08;stm32f1xx.it.c&#xff09;&#xff0c;用户配置文件&#xff08;stm32f1xx_hal_conf.h&#xff09;等用户程序文件&#xff0c;或者mdk启动程序…