[week15] B - ZJM与生日礼物(选做)—— 字典树

2023-05-16

文章目录

  • 题意
    • Input
    • Output
    • 输入样例
    • 输出样例
    • 提示
  • 分析
  • 总结
  • 代码

题意

ZJM 收到了 Q老师 送来的生日礼物,但是被 Q老师 加密了。只有 ZJM 能够回答对 Q老师 的问题,Q老师 才会把密码告诉 ZJM。

Q老师 给了 ZJM 一些仅有 01 组成的二进制编码串, 他问 ZJM:是否存在一个串是另一个串的前缀.

Input

多组数据。每组数据中包含多个仅有01组成的字符串,以一个9作为该组数据结束的标志。

Output

对于第 k 组数据(从1开始标号),如果不存在一个字符串使另一个的前缀,输出"Set k is immediately decodable",否则输出"Set k is not immediately decodable"。
每组数据的输出单独一行

输入样例

01
10
0010
0000
9
01
10
010
0000
9

输出样例

Set 1 is immediately decodable
Set 2 is not immediately decodable

提示


分析

这也是一道用字典树解决的字符串问题。


  • 字典树

1. 什么是字典树?字典树的作用?

字典树就是指的每个节点存储的都是一个字符的树。从根到任意一个叶子经过的路径就代表着一个完整字符串。

字典树主要用于判断一个字符是否是另一个字符的前缀。

2. 字典树类型

字典树类型:

  • 节点
    每个节点有唯一的序号标记
  • 根节点
  • 孩子数组
    用一个二维数组记录每一个节点存在哪些孩子。
    child[n][m]:n代表节点序号,m代表孩子类型,存储的是孩子节点的序号。
  • 结尾数组
    用一个数组标记每个字符串的结尾节点。
    flag[n]:n代表节点序号。若赋为true说明该节点是一个字符串的结尾。

3. 字典树构造

每一次插入都从根节点开始,依次插入字符串中的每一个字符:

  • 判断当前节点i是否已经存在和当前待插入字符类型x相同的孩子
    • 若没有,则新建节点(最新序号tot + 1)存储该字符。在孩子数组中,将节点i对应字符类型x的数组空间赋值为该新节点序号tot + 1 ——> child[i][x] = tot + 1
    • 若已有,则判断该字符是否为当前字符串的结尾或是否为已存在字符串的结尾:
      • 若是当前字符串的结尾,则说明当前字符串一定被另一个已插入字符串包含;否则继续插入
      • 若是已存在(已插入树中)字符串的结尾,则说明当前正在插入的字符串一定包含一个完整的字符串;否则继续插入
  • 当前字符插入后,将判断节点更新为新插入的节点,重复上述步骤
  • 当字符串插入完成后,将最后一个判断节点标记为结尾节点

4. 字典树判断原理

根据前面的介绍我们已经知道,从根到任意叶子的路径都是一个完整的字符串。

但是可以想到,若字符串a包含字符串b,则字符串b无法从根走到任何一个叶子,而是属于a这条从根到叶子的路径中的一部分。

显然,判断两个字符串之间结尾节点的关系就是判断两个字符串包含关系的关键。

若仅存在两个字符串a和b,其中a已插入字典树中:

  • 若当前b的某一个字符已经被标记为结尾节点,则代表a字符串从根开始沿相同路径到该字符处结束。显然b包含a。
  • 若b的最后一个字符已经存在于字典树中,则代表b在完整走完a这条路径之前就提前结束。显然a包含b。

需要注意的是:

假设两个字符串a和b,长度分别为l1和l2(l1 >= l2)

若a和b前l3长度都完全相同,则显然它们插入在字典树的位置完全相同。
若第l3 + 1个字符不同,则a和b的第l3 + 1个字符将分别被插入在第l3个字符的不同孩子位置处。
就算剩下的所有字符都相同,a和b在第l3 + 1个之后的所有字符都将属于完全不同的路径。

这就是前面判断的基础。若一个节点已存在,则说明其一定属于于一个已存在的字符串中,只要该节点是一个结尾节点,不论其属于谁,都一定代表着存在包含关系。


  • 题目分析

这就是一道典型的字典树问题。需要注意的是这个题目中涉及到的字符类型只有2种,即0和1。因此孩子数组中第二维只需要设置为2,即代表对每个节点来说会有0和1两个类型的孩子。


总结

  1. 字符串还挺有意思😮

代码

//
//  main.cpp
//  lab2
//
//

#include <iostream>
#include <string.h>
#include <string>
using namespace std;

struct Tree         //字典树
{
    static const int N = 100000;        //最大节点数
    static const int charset = 2;       //字符种类
    int tot;            //最新节点序号
    int root;           //字典树根
    int child[N][2];        //第n个节点的孩子
    bool flag[N];            //标记第n个节点是否属于一个字符串的结尾
    
    Tree()          //构造函数
    {
        memset(child,-1,sizeof(child));
        root = 0;
        tot = 0;
    }
    
    void clear()        //清空
    {
        memset(child,-1,sizeof(child));
        root = 0;
        tot = 0;
    }
    
    bool insert(string s)     //插入字符串
    {
        int now = root;    //从根开始逐个插入每个字符
        bool judge = false;     //返回判断结果
        
        for( int i = 0 ; i < s.size() ; i++ )        //逐个插入字符串中的每个字符
        {
            int x = s[i] - '0';       //得到孩子序号
            
            if( child[now][x] == -1 )       //若当前节点不存在这个孩子
            {
                child[now][x] = ++tot;      //插入孩子,孩子所代表节点序号+1
                flag[now] = 0;              //标记该孩子节点不为结尾
            }
            else if( i == s.size() - 1 || flag[child[now][x]] )
                judge = true;
            //若当前节点已有该孩子,则判断该节点是否是结尾,若是则说明存在前缀
            
            now = child[now][x];        //从当前孩子节点向下继续添加
        }
        
        flag[now] = 1;      //标记最后一个节点为一个结束节点
        
        return judge;       //返回结果
    }
    
};


int main()
{
    ios::sync_with_stdio(false);
    
    int k = 0;
    string s;
    Tree t;
    bool judge = false;
    
    while( cin>>s )
    {
        if( s == "9" )
        {
            if( !judge )
                cout<<"Set "<<++k<<" is immediately decodable"<<endl;
            else
                cout<<"Set "<<++k<<" is not immediately decodable"<<endl;
            
            t.clear();
            
            judge = false;
            
        }
        else
        {
            if( t.insert(s) )       //只要有一个存在前缀则该组数据合法
                judge = true;
        }
    }
    
    return 0;
}




本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[week15] B - ZJM与生日礼物(选做)—— 字典树 的相关文章

随机推荐

  • 将arduino uno的数据上传到云平台

    文章目录 将arduino uno的数据上传到云平台解决方案adruino uno方面代码esp8266 方面代码主函数阿里云sdkcpp部分函数头部分 将arduino uno的数据上传到云平台 解决方案 加一块esp8266的单片机 x
  • 华为IS-IS基础配置

    目录 一 原理概述 二 实验要求 三 实验拓扑 四 实验步骤 一 原理概述 1 IS IS xff1a Intermediate System to Intermediate System xff0c 中间系统到中间系统 2 链路状态协议
  • 基于markdown-it打造的markdown编辑器

    前言 markdown it是一个用来解析markdown的库 xff0c 它可以将markdown编译为html xff0c 然后解析时markdown it会根据规则生成tokens xff0c 如果需要自定义 xff0c 就通过rul
  • WiFi模块ESP-07s开发过程(学习笔记)

    目录 注意事项获取AT指令用到的指令通过返回的指令提取自己想要的信息 注意事项 转义字符 xff1a xff1a C中定义了一些字母前加 34 34 来表示常见的那些不能显示的ASCII字符 xff0c 如 0 t n等 xff0c 就称为
  • Vue3 table表格使用axios调用后端Api数据,统一返回格式

    1 安装axios npm install axios 2 封装axios span class token keyword import span span class token namespace axios span span cl
  • 关于C++的string字符串拼接问题(和“字符转字符串”问题有关)

    xff08 只有气到我肺都炸了的情况下我才可能废一些时间去写博客 xff08 主要是写一些气话 xff09 xff0c 但现在气消得差不多了我也骂不出什么话了 正文 1 字符串拼接分软拼接和硬拼接 xff08 软硬拼接 是我自己发明的词 实
  • [week2]化学——识别烷烃基

    文章目录 题意InputOutput输入样例输出样例 分析总结代码 题意 化学很神奇 xff0c 以下是烷烃基 假设如上图 xff0c 这个烷烃基有6个原子和5个化学键 xff0c 6个原子分别标号1 6 xff0c 然后用一对数字 a b
  • [week2]模拟OJ成绩排名系统(简易版)

    文章目录 题意InputOutput输入样例输出样例 分析总结代码 题意 题面宛如小作文233 程序设计思维作业和实验使用的实时评测系统 xff0c 具有及时获得成绩排名的特点 xff0c 那它的功能是怎么实现的呢 xff1f 我们千辛万苦
  • [week3]区间选点问题——贪心算法

    目录 题意InputOutput输入样例输出样例 分析总结代码 题意 数轴上有 n 个闭区间 a i b i 取尽量少的点 xff0c 使得每个区间内都至少有一个点 xff08 不同区间内含的点可以是同一个 xff09 Input 第一行1
  • [week3]区间覆盖问题——贪心算法

    目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 数轴上有 n 1 lt 61 n lt 61 25000 个闭区间 ai bi xff0c 选择尽量少的区间覆盖一条指定线段 1 t xff08 1 lt 61 t
  • [csp模拟1]咕咕东的奇遇——(一)

    目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 咕咕东是个贪玩的孩子 xff0c 有一天 xff0c 他从上古遗迹中得到了一个神奇的圆环 这个圆环由字母表组成首尾相接的环 xff0c 环上有一个指针 xff0c 最
  • Linux挂载镜像的一些命令

    Linux挂载镜像的一些命令 在Linux中 xff0c 可以用losetup命令来设置无分区空白镜像到loop设备上 xff0c 用kpartx 来kpartx映射分区的镜像到loop设备上 之后通过mount命令将loop设备与系统文件
  • [week5]平衡字符串——尺取法

    目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 一个长度为 n 的字符串 s xff0c 其中仅包含 Q W E R 四种字符 如果四种字符在字符串中出现次数均为 n 4 xff0c 则其为一个平衡字符串 现可以将
  • [csp模拟2]T4——咕咕东的奇妙序列

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 咕咕东 正在上可怕的复变函数 xff0c 但对于稳拿A Plus的 咕咕东 来说 xff0c 她早已不再听课 xff0c 此时她在睡梦中 突然想到了一个奇怪的无限
  • [week9]签到题(长凳)——贪心算法

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 SDUQD 旁边的滨海公园有 x 条长凳 第 i 个长凳上坐着 a i 个人 这时候又有 y 个人将来到公园 xff0c 他们将选择坐在某些公园中的长凳上 xff
  • [week14] Q老师与十字叉

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 Q老师 得到一张 n 行 m 列的网格图 xff0c 上面每一个格子要么是白色的要么是黑色的 Q老师认为失去了 十字叉 的网格图莫得灵魂 一个十字叉可以用一个数对
  • [week15] ZJM 与霍格沃兹 —— 字符串哈希

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 ZJM 为了准备霍格沃兹的期末考试 xff0c 决心背魔咒词典 xff0c 一举拿下咒语翻译题 题库格式 xff1a 魔咒 对应功能 背完题库后 xff0c ZJ
  • [week14] D - Q老师染砖(选做) —— 矩阵快速幂优化DP

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 衣食无忧的 Q老师 有一天突发奇想 xff0c 想要去感受一下劳动人民的艰苦生活 具体工作是这样的 xff0c 有 N 块砖排成一排染色 xff0c 每一块砖需要
  • [week14] E - Q老师度假(选做)—— 矩阵快速幂优化DP(拓展)

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 忙碌了一个学期的 Q老师 决定奖励自己 N 天假期 假期中不同的穿衣方式会有不同的快乐值 已知 Q老师 一共有 M 件衬衫 xff0c 且如果昨天穿的是衬衫 A
  • [week15] B - ZJM与生日礼物(选做)—— 字典树

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 ZJM 收到了 Q老师 送来的生日礼物 xff0c 但是被 Q老师 加密了 只有 ZJM 能够回答对 Q老师 的问题 xff0c Q老师 才会把密码告诉 ZJM