201809-3 CCF 元素选择器 满分题解(超详细注释代码) + 解题思路(超详细)

2023-05-16

问题描述

在这里插入图片描述

解题思路

根据题意可以知道在查询中可以分为两种情况
第一种是查询一个标签选择器或者id选择器(可以称为一级查询
第二种就是存在大于两级的查询(可以称为多级查询

显然第一种查询需要存储每一种元素在内容中所有出现的行,对应的数据结构可以是unordered_map< string, vector < int > >

对于第二种多级查询,例如查询所有满足 A B C D的位置
首先将所有D出现的位置找出来,也就是上面那个map中存的vector数组
遍历这个数组,相当于遍历每一条以D结尾的路径
对于每一条以D结尾的路径,从D开始回溯,每次回溯到当前行的父亲行(这里需要一个p数组记录父亲行的位置),并且如果路径中的该行中有元素与查询的最后一个元素匹配(这个匹配需要map来记录每一行有哪些元素,对应的数据结构可以是unordered_map < int, unordered_map < string, int > >),则查询元素弹出
当以D结尾的路径遍历完时,并且查询中的元素也为空,则说明这条路径能够满足查询,则将这个答案保存下来

至于p数组中的值,就是利用一个数组记录每一行之前最近的起始行就可以得到,具体可见代码,不难理解
至于两个map中的值,主要是利用双指针还有substr等函数,具体可见代码,不难理解


代码实现

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <unordered_map>

using namespace std;
const int N = 110;

vector <string> text;
int n, m;
int p[N];
unordered_map <string, vector <int>> val; //存储每一个元素对应的行号
vector<vector <string>> query; //存储所有的查询
unordered_map <int, unordered_map<string, int>> value; //存储每一行有哪些元素,相当于一个可哈希的二维数组

//将每一行的父亲行存入p数组,并且去除每一行前面的.
void workparent()
{
    //先将每一行开头的点数存储在p数组中,并去除.
    for (int i = 1; i <= n; i ++)
    {
        string str = text[i];
        int j = 0;
        while (j < str.size() && str[j] == '.') j ++; //j停在第一个不是.的位置
        text[i] = str.substr(j); //去除前面的点
        p[i] = j; //保存第i行内容前面.的个数
    }
    
    //从头遍历p数组,更新p数组,将p数组存储第i行的父亲行,用t数组存储最近的有p[i] - 2个.的位置
    int t[N];
    memset(t, 0, sizeof(t));
    for (int i = 1; i <= n; i ++)
    {
        t[p[i]] = i; //更新最近的一个有p[i]个点的位置
        if (p[i] == 0) continue;
        int f = t[p[i] - 2]; //父亲节点是最近的有p[i] - 2个点的位置
        p[i] = f; //存储第i行元素的父节点行数
    }
}
 
//将每一行询问根据空格分隔存储
void workquery()
{
    for (int i = n + 1; i <= n + m; i ++) //读入的询问行
    {
        string str = text[i];
        vector <string> r;
        for (int j = 0; j < str.size(); j ++)
        {
            int k = j;
            string t;
            while (k < str.size() && str[k] != ' ') t += str[k ++]; //k越界或k是空格
            if (t[0] != '#') transform(t.begin(), t.end(), t.begin(), ::tolower); //可以转包含数字的串!
            r.push_back(t); //将每一个元素存入r
            j = k;
        }
        query.push_back(r);
    }
}

//存储每一行元素的对应行数
//存储每一行对应有哪些元素
void workpos()
{
    for (int i = 1; i <= n; i ++)
    {
        string str = text[i];
        for (int j = 0; j < str.size(); j ++)
        {
            int k = j;
            string t;
            while (k < str.size() && str[k] != ' ') t += str[k ++]; //k越界或k是空格
            if (t[0] != '#') transform(t.begin(), t.end(), t.begin(), ::tolower);
            val[t].push_back(i); //存储t元素的对应行数i
            value[i][t] = 1;//存储i行有元素t
            j = k;
        }
    }
}

int main()
{
    cin >> n >> m;

    getchar();
    text.push_back("*"); //使下标从1开始
    for (int i = 0; i < n + m; i ++) //读入所有内容包括询问
    {
        string str;
        getline(cin, str);
        text.push_back(str); //1 ~n, n + 1 ~n + m
    }

    workparent(); //找到所有行的父亲行
    workpos(); //存储每一行元素对应的行数
    workquery(); //将询问处理并分隔

    //进行询问的查询
    for (int i = 0; i < query.size(); i ++)
    {
        vector <string> q = query[i];
        vector <int> r = val[q.back()]; //r包含最后一个元素出现的所有位置
        if (q.size() == 1) //一代
        {
            cout << r.size(); //是0的话就不会输出!
            for (auto x : r) cout << " " << x;
        }
        else //多代
        {
            vector <int> res;
            for (auto pathend : r) //遍历每一条路
            {
                vector <string> flag = q; //标记数组存储的是一行查询的元素,如果路径上出现数组中的末尾元素,就将末尾元素弹出
                for (int row = pathend; row != 0 && !flag.empty(); row = p[row]) //结束条件,标记数组空了或者路走到了尽头
                {
                    if (value[row][flag.back()]) flag.pop_back();
                }
                if (flag.empty()) res.push_back(pathend); //表明以pathend结尾的路径上能满足该行询问,将这个元素位置加入答案中
            }
            cout << res.size();
            for (auto x : res) cout << " " << x;
        }
        cout << endl;
    }
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

201809-3 CCF 元素选择器 满分题解(超详细注释代码) + 解题思路(超详细) 的相关文章

  • 【51单片机】 蜂鸣器发声程序

    蜂鸣器分为有源和无源 xff0c 这个源是震荡源 有源的直接给高电平就可以响 xff08 也有低电平驱动 xff09 无源的还需要通过给一个持续到震荡源才能作用 51单片机开发板上的蜂鸣器通常是无源的 以下是蜂鸣器发声程序 span cla
  • 【51单片机】 A4988驱动模块驱动四线步进电机

    A4988是控制双极步进电机的驱动模块 在本文中 xff0c 我们学习如何使用它控制步进电机 A4988的逻辑电压范围是 xff1a 3 5 5V xff0c 如果配备较好的散热条件每相最大电流可达2A xff0c 在没有配备散热器的情况下
  • 3.1 用ffmpeg解决音画不同步问题

    当前问题 xff1a 音画不同步 xff0c 声音滞后于画面 解决方法 xff1a ffmpeg itsoffset 00 00 00 900 i whs sec08 mp4 i whs sec08 mp4 map 0 v map 1 a
  • 【51单片机】利用烧录软件生成延时函数 入门学习

    1 打开烧录软件 2 xff08 1 xff09 找到延时计算器 xff08 2 xff09 选择晶振 xff08 11 0592和12Mhz的情况下建议都选择12Mhz xff09 xff08 3 xff09 选择时间单位us 或者 ms
  • 【51单片机】0.96寸OLED取模教程(图片、汉字)+ 代码

    在文章开头必须值得一提的是 xff1a 文字和图片的取模并非是在网上随便找一篇文章如法炮制就行的 xff0c 主要是看自己的代码读取是怎么写的 xff0c 根据实际情况进行取模 xff0c 才能实际在oled显示出来 本文把oled工程模板
  • 【51单片机】74HC595串转并 使用

    74HC595通常是用来解决单片机I O口不够用的情况 如果你对该芯片没有任何的了解 xff0c 建议先观看以下两篇文章 xff0c 它会对你接下来的使用很有帮助 如果你只想直接快速能上手使用 xff0c 那么请跳过两篇文章 xff0c 直
  • STC12C5A60S2最小系统

    STC12C5A60S2最小系统 xff0c 跟51一个样的 初学者自己焊接最小系统的时候不要忘了共VCC和共地 xff0c 就是电路中所有VCC连接一起 xff0c 接地也是 xff0c 这是新手比较容易忽视的问题
  • 水位传感器(Water Sensor)原理图

    写资料 论文用 2022年5月23日应要求 xff0c 重新更新了一张 xff0c 主要还是平行导线没有找到太好的方法 xff0c 所以就随便画了几根主线代替一下 xff0c 如果有更好的办法可以留言我 另外 xff0c 为了照顾一些不需要
  • 光敏电阻简单应用——晚上灯亮,白天灯灭

    光敏电阻就是对光比较敏感一种类型的电阻 常见光敏电阻有以下特性 xff1a 光度越亮 xff0c 电阻越小 xff1b 环境越暗 xff0c 电阻越大 那么 xff0c 如何利用光敏电阻特性 xff0c 在晚上的时候灯可以点亮 xff0c
  • 单片机小精灵(延时、定时计算软件)

    使用延时计算软件可以省略自己计算的时间 xff0c 大大提高效率 使用方式 xff1a 1 选择单片机晶振频率 xff0c 一般是 11 0592 和 12 MHz 2 选择单片机模式 xff0c C51 C52系列一般都是12T 不清楚可
  • 【STM32F103】0.96寸OLED工程模板

    主程序页面 xff1a OLED显示页面 xff1a 可实现功能函数 xff1a 百度云链接 xff1a 0 96寸OLED工程模块https pan baidu com s 1a1ae4NQSUZh0Cb5EyUGuEg https pa
  • 整流电路详解

    整流电路定义 什么是整流电路 xff1f 整流电路说的是把交流电转化为直流电 xff0c 一般情况下是由变压器 整流主电路和滤波电路构成 xff0c 如果想得到一个恒定的电压值 xff0c 这里还需要加上一个稳压电路 稳压电路先不说 xff
  • PCF8591 A/D转换模块

    PCF8591 的通信接口是 IIC协议 xff0c 编程需要对 PCF8591 进行初始化 PCF8591接线原理图 xff1a AIN0 AIN3 模拟信号的4个输入端口A0 A2 芯片地址低三位 VDD GND 电源 地 电源电压2
  • Golang和Qt, 开发桌面应用程序

    简单的例子 参考 https tw saowen com a e0496e173ca67dd7f0dc111cbcb872a53a14d8275e750219f5d2854c82c05749 https github com thereci
  • DY-SV17F语音播放模块应用篇一 【IO独立模式】

    DY SV17F模块模式分为I O组合模式和I O独立模式 xff0c 每种模式下又有两种方式 按键触发模式和电平触发模式 xff0c 低电平有效 注 按键触发是指低电平触发后随即释放电平 xff0c 类似于按键按下后弹起 xff0c 故称
  • 同步串行通信、异步串行通信、并行通信的区别

    一 什么是同步 异步 xff1f 同步 xff1a 通迅双方靠一条时钟线约定速率 异步 xff1a 通迅双方各自约定速率 传送的消息必须有起始位 校验位和结束位 等信号 xff0c 确保接收的信息不出错 二 什么是串行 并行 xff1f 串
  • 同相比例和反相比例运算放大电路

  • 【51】PWM控制使用

    PWM xff0c 英文名Pulse Width Modulation xff0c 是脉冲宽度调制缩写 xff0c 它是通过对一系列脉冲的宽度进行调制 xff0c 等效出所需要的波形 xff08 包含形状以及幅值 xff09 通过调节占空比
  • STM32的八种工作模式

    一 模式介绍 STM32单片机具有高性能 低成本 低功耗的优点 xff0c 与它打交道就必须先了解它的几种工作模式 xff0c 它共有八种IO口模式 xff0c 分别是 xff1a 模拟输入 浮空输入 上拉输入 下拉输入 开漏输出 推挽输出
  • linux远程管理

    linux远程管理 一 关闭与重启二 查看或配置网卡信息三 远程连接ssh四 远程复制scp五 免密码登录与别名六 修改shell七 通过域名找IP地址 一 关闭与重启 shutdown 一分钟后关机 shutdown span class

随机推荐

  • 逃离塔克夫TT辅助注入器再次更新0.56

    更新版本有0 12 7 9018和0 12 4 6297的辅助TT 2021年6月12日14 xff1a 50更新 下载加群 xff1a 821414423 部分截图 免费 xff01
  • spring junit测试时下面爆红javax.net.ssl.SSLException的解决方法

    做软工三项目时 xff0c 发现测试用例通过了 xff0c 但控制台最下面仍然爆红 xff1a 解决方法 xff1a 在application yml的database url后面加上 xff1a amp useSSL 61 false 然
  • 设计模式:(生成器模式)

    1 定义 建造者模式 xff08 Builder Pattern xff09 使用多个简单的对象一步一步构建成一个复杂的对象 这种类型的设计模式属于创建型模式 xff0c 它提供了一种创建对象的最佳方式 一个 Builder 类会一步一步构
  • Anaconda添加、删除、查找环境变量 +添加conda为内部变量

    1 conda不是内部变量 xff0c 怎么办 xff1f 此电脑 属性 高级系统设置 环境变量 双击Path 新建 浏览 2 安装Anconda是否成功 打开cmd W 43 R 输入 xff1a conda V 3 conda安装有哪些
  • 移动立方体(Marching Cubes,MC)算法

    移动立方体 xff08 Marching Cubes xff09 算法是面绘制算法中的经典算法 xff0c 它是W Lorensen等人于1987年提出的体素级重建算法 xff0c 也被称为 等值面提取 xff08 Isosurface E
  • iOS中的表视图

    表视图 1 表视图分类 普通表视图 主要用于动态表 xff0c 一般在单元格数目未知的情况下使用 分组表视图 xff1a 可以用于动态表和静态表 动态表分组时 xff0c 单元格分成不同的部分 xff0c 而每一部分中单元格中的数据是相似的
  • 1.文件包含漏洞

    一 什么是文件包含漏洞 随着网站业务的需求 程序开发人员一般希望代码更灵活 所以将被包含的文件设置为变量 用来进行动态调用 但是正是这种灵活性通过动态变量的方式引入需要包含的文件时 用户对这个变量可控而且服务端又没有做合理的校验或者校验被绕
  • Java:用Java程序打印出所有的 “水仙花数 ”。

    题目 xff1a 利用Java程序打印出所有的 34 水仙花数 34 所谓 34 水仙花数 34 是指一个三位数 xff0c 其各位数字立方和等于该数本身 例如 xff1a 153是一个 34 水仙花数 34 xff0c 因为153 61
  • Ubuntu22 使用devstack一键部署OpenStack

    一 虚拟机准备 主要是因为上次安装稀里糊涂找的教程 xff0c 后来有问题了哈哈 xff0c 这次仔细看了油管教程还有官网教程 xff0c 记录一下后面要是出问题了方便重装哈哈 配置 xff1a 1 进入root账号 sudo passwd
  • 素数筛(埃拉托斯特尼筛和欧拉筛)

    线性筛素数 题目描述 给定一个范围 n xff0c 有 q 个询问 xff0c 每次输出第 k 小的素数 输入格式 第一行包含两个正整数 n q分别表示查询的范围和查询的个数 接下来 q行每行一个正整数 k xff0c 表示查询第 k小的素
  • typescript 错误码大全

    转载于https www easemob com question 6196 1002 错误 Unterminated string literal 未终止的字符串文本 1003 错误 Identifier expected 应为标识符 1
  • 《C++ 新经典》 并发与多线程

    文章目录 本章内容概述一 基本概念1 并发 xff0c 进程 xff0c 线程2 并发的实现2 1 多进程并发2 2 多线程并发 3 C 43 43 11 新标准线程库 二 线程基本使用1 线程创建与启动2 其余线程创建方法 三 线程参数传
  • 基于 Linux 的 Ngina-server 通信架构 C++ 实现

    文章目录 本章内容概述一 项目概述1 项目描述2 项目技术 二 项目详解1 项目框架2 项目流程 三 项目拓展1 简要介绍一下你的项目 xff1f 2 项目程序结构 xff1f 3 线程之间如何同步 xff1f 4 如何处理客户端发送的数据
  • ubuntu 查看占用文件空间大小

    1 查看分区情况 fdisk l 2 查看系统的磁盘空间占用情况 df h df TH 3 查看某个目录的使用空间大小 du sh 需要先进入该目录 或者后面加上路径 du sh 路径 4 查看该目录下 每个文件夹占用的空间大小 查看某目录
  • 七段码(蓝桥杯真题)——python求解

    题目如下 xff1a 小蓝要用七段码数码管来表示一种特殊的文字 上图给出了七段码数码管的一个图示 xff0c 数码管中一共有 7 段可以发光的二极管 xff0c 分别标记为 a b c d e f g 小蓝要选择一部分二极管 xff08 至
  • 【Ubuntu】解决安装显卡驱动后无法进入系统

    像这样 xff08 图片来源于网络 xff0c 侵删 xff09 xff1a 这是显卡驱动安装不正确造成的 解决方法 下载一个easyBCD xff0c 在windows系统下 xff08 双系统 winpe xff09 编辑引导分区 xf
  • 放苹果(递归)

    问题描述 把m个同样的苹果放在n个同样的盘子里 xff0c 允许有的盘子空着不放 xff0c 问有多少种不同的分法 xff1f 注 xff1a 5 1 1和1 1 5是同一种分法 输入 苹果个数m 和盘子个数n 0 lt 61 M xff0
  • 利用冒泡排序,输入10个数字,从小到大排序并输出

    如果有n个数 xff0c 要进行n 1趟比较 xff0c 在第一趟要进行n 1次两两比较 xff0c 在第j趟要进行n j次两两比较 include lt stdio h gt int main int a 10 i j t printf
  • CCF 炉石传说 满分代码(详细注释) + 解题思路 (结构体模拟) 201609-3

    题目描述 解题思路 将每个人用结构体存储生命和攻击力 用一个结构体二维数组存储所有人员信息 p 0 0 存储先手英雄 xff0c p 0 1 7 存储先手的随从 p 1 0 存储先手英雄 xff0c p 1 1 7 存储先手的随从 读入n个
  • 201809-3 CCF 元素选择器 满分题解(超详细注释代码) + 解题思路(超详细)

    问题描述 解题思路 根据题意可以知道在查询中可以分为两种情况 第一种是查询一个标签选择器或者id选择器 xff08 可以称为一级查询 xff09 第二种就是存在大于两级的查询 xff08 可以称为多级查询 xff09 显然第一种查询需要存储