Trie字符串统计-java

news2024/11/16 1:38:16

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.coloradmin.cn/o/1711623.html

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

相关文章

以果决其行,只为文化的传承

从他们每一个人的身上&#xff0c;我们看到传神的东西&#xff0c;就是他们都能用结果&#xff0c;去指引自己前进的方向&#xff0c;这正是我要解读倪海厦老师的原因&#xff0c;看倪海厦2012年已经去世&#xff0c;到现在已经十几年时间了&#xff0c;但是我们看现在自学中医…

【设计模式深度剖析】【6】【结构型】【外观模式】| 以电脑开关按钮为例,并结合微服务架构的API网关加深理解

&#x1f448;️上一篇:桥接模式 设计模式-专栏&#x1f448;️ 目 录 外观模式&#xff08;Facade Pattern&#xff09;定义英文原文直译如何理解呢&#xff1f;字面理解代码实现中的理解生活案例&#xff1a;操作多功能料理机典型案例分析&#xff1a;API网关与外观模式 外…

STM32H750外设之ADC连续转换模式

目录 概述 1 ADC数据转换模式介绍 1.1 功能介绍 1.2 ADCx_CFGR 2 连续转换模式 (CONT1) 2.1 功能介绍 2.2 连续转换模式 2.3 转换序列完成 3 注意问题 概述 本文主要介绍STM32H750外设之ADC连续转换模式的相关内容&#xff0c;包括与之相关的寄存器的控制位bit。每个…

详解makefile中的foreach

在 Makefile 中&#xff0c;foreach 函数用于迭代处理一个以空格分隔的列表&#xff0c;并针对列表中的每个元素执行相同的操作。这个函数通常用于循环处理一组变量或文件名&#xff0c;并执行相同的规则或命令。 语法&#xff1a; makefile Copy Code $(foreach var, list, …

四川古力未来科技抖音小店安全靠谱,购物新体验

在数字化浪潮席卷而来的今天&#xff0c;电商行业蓬勃发展&#xff0c;各种线上购物平台如雨后春笋般涌现。其中&#xff0c;抖音小店凭借其独特的短视频直播购物模式&#xff0c;迅速赢得了广大消费者的青睐。而四川古力未来科技抖音小店&#xff0c;更是以其安全靠谱、品质保…

单点11.2.0.3备份恢复到单点11.2.0.4

保命法则&#xff1a;先备份再操作&#xff0c;磁盘空间紧张无法备份就让满足&#xff0c;给自己留退路。 场景说明&#xff1a; 1.本文档的环境为同平台、不同版本&#xff08;操作系统版本可以不同&#xff0c;数据库小版本不同&#xff09;&#xff0c;源机器和目标机器部…

广东省保健食品行业协会批复成为“世界酒中国菜”活动指导单位

广东省保健食品行业协会正式批复成为“世界酒中国菜”系列活动指导单位&#xff0c;共促餐饮文化交流发展 近日&#xff0c;广东省保健食品行业协会正式批复荐酒师国际认证&#xff08;广州&#xff09;有限公司&#xff0c;成为备受瞩目的“世界酒中国菜”系列活动的指导单位…

【Linux】初识Linux和Linux环境配置

1.什么是Linux操作系统 说到电脑系统 我想有大多数人会脱口而出&#xff1a;windows、mac 是的&#xff0c;这也是如今市场上主流的两种操作系统。 但是对于IT相关的人士来说&#xff0c;还有一种系统也是必须有姓名 那就是Linux Linux&#xff0c;Linux Is Not UniX 的…

Python Hydra:现代开发者的配置管理神器

更多Python学习内容&#xff1a;ipengtao.com Hydra是一个用于配置管理的强大工具&#xff0c;旨在帮助开发者处理复杂的应用程序配置。它支持多层次的配置合并、命令行覆盖、动态配置和实验管理。Hydra特别适用于需要处理大量配置参数的机器学习和深度学习项目。本文将详细介绍…

《公正》孙溟㠭艺术

孙溟㠭艺术《公正》 孙溟㠭艺术《公正》

​一款开源的.NET程序集反编译、编辑和调试神器

前言 说到.NET相关的反编译工具大家脑海里第一个想到的工具是什么&#xff1f;ILSpy、dnSpy、还是dotPeek&#xff1f;咱们今天的主要内容是讲讲dnSpyEx&#xff08;dnSpyEx是dnSpy项目的非官方Fork维护版本&#xff09;这个开源的.NET程序集反编译、编辑和调试工具该如何使用…

RT-DETR算法改进【NO.1】借鉴CVPR2024中的StarNet网络StarBlock改进算法

前 言 YOLO算法改进的路有点拥挤,尝试选择其他的baseline作为算法研究,可能会更加好发一些文章。后面将陆续介绍RT-DETR算法改进的方法思路。 很多朋友问改进如何选择是最佳的,下面我就根据个人多年的写作发文章以及指导发文章的经验来看,按照优先顺序进行排序讲解…

温度传感器安装热套管介绍

热套管&#xff08;Thermowell&#xff09;是一段末端封闭的金属管&#xff0c;主要通过焊接、螺纹或法兰连接的方式安装到过程容器或管线上&#xff0c;可保护温度传感器免受流致应力、高压和腐蚀性化学品等严苛工况的影响。此外&#xff0c;热套管使传感器可以轻松方便地拆下…

让 AI 回答更精准 来学学这些Prompt入门小技巧

&#x1f3a5;前言 最近一直在研究各种 AI 提问相关的方法&#xff0c;一顿输入后&#xff0c;get到了好多有趣又好玩的提问小技巧。今天就来和小伙伴们安利下&#xff0c;平常在向AI提问时&#xff0c;最最基础&#xff0c;且最最实用的6种提示词方法。 那废话不多说&#x…

德克萨斯大学奥斯汀分校自然语言处理硕士课程汉化版(第二周) - 多类别分类和神经网络

多类别分类和神经网络 1. 多类别分类2. 多类别感知机和多类别逻辑回归3. 多类别分类的场景4. 分类公平性5. 神经网络6. 神经网络可视化7. 神经网络的前向传播和反向传播8. 神经网络的训练与优化 1. 多类别分类 分类是一个预测建模问题&#xff0c;它涉及到在给定输入的情况下…

8.2 数组遍历访问

本节必须掌握的知识点&#xff1a; 示例三十 代码分析 汇编解析 在上一节中介绍了数组相关的概念&#xff0c;而在本节中将介绍数组的使用。 8.2.1 示例三十 ■访问数组 示例代码三十 ●第一步&#xff1a;分析需求&#xff0c;设计程序…

【C语言习题】26.字符逆序

文章目录 1.描述2.解题思路3.具体代码 1.描述 输入描述: 将一个字符串str的内容颠倒过来&#xff0c;并输出。可以有空格 数据范围&#xff1a;1≤&#x1d459;&#x1d452;&#x1d45b;(&#x1d460;&#x1d461;&#x1d45f;)≤10000 1≤len(str)≤10000 输出描述&…

httpJVM

目录 HTTPS如何保证安全 1&#xff09;引入非对称加密 2&#xff09;引入非对称加密 3.中间人攻击 4.解决中间人攻击 JVM 1.JVM内存划分 2.JVM类加载过程 八股内容 3.JVM中的垃圾回收机制 释放垃圾的策略 1.标记-清除 2.复制算法 3.标记-整理 分代回收 HTTPS如何…

基于JCEF实现网页资源性能分析

文章目录 1、需求2、实现代码3、运行效果 1、需求 在使用chrome浏览器访问页面时&#xff0c;浏览器自带的开发者工具可以查看页面每个资源的资源大小和加载时间。 这个功能可以让我们直接知道接口或资源的耗时情况和大小情况&#xff0c;如果存在性能问题&#xff0c;可以进…

AST反混淆|对一段非常复杂的混淆代码深度剖析与还原

关注它&#xff0c;不迷路。 本文章中所有内容仅供学习交流&#xff0c;不可用于任何商业用途和非法用途&#xff0c;否则后果自负&#xff0c;如有侵权&#xff0c;请联系作者立即删除&#xff01; 1.代码片段 ((((ld0 ((ld1 (ld1 Uint8Array) && undefined…