CCF-CSP题解 201809-3 元素选择器
题目要求写一个简易的CSS Selector。
首先用结构体\(<lev,label[],hasId,id[]>\)存储元素。其中\(lev\)表示元素在html树中的深度(这个是因为逻辑凌乱才加上的
接着用链式前向星存储html元素树。这里用一个栈\(rootStack\)方便找到新元素的父亲节点\(temp\)。
三种选择器都可以归结为第三种方式——后代选择器。
题目里已经给了算法:在匹配时,可以采用贪心的策略,除最后一级外,前面的部分都可以尽量匹配层级小的元素。写个dfs就好了。
注意标签不区分大小写,不可以直接用strcmp的。
字符串处理有点不方便。要熟练掌握%s,%[^],getchar,fgets,sscanf及相关函数。
#include <bits/stdc++.h>
const int maxn = 100;
const int maxm = 80; // max length of one element
using namespace std;
char line[maxm+10];
struct tElement
{
int lev;
char label[maxm+10];
bool hasId;
char id[maxm+10];
tElement()
{
hasId = false;
}
};
tElement element[maxn+10];
int to[maxn+10];
int nex[maxn+10];
int head[maxn+10];
char selector[maxm/2+10][maxm+10];
bool labelEqual(char s1[], char s2[])
{
if (strlen(s1) != strlen(s2))
return false;
for (int i = 0; s1[i] != '\0'; i++)
{
if (!((s1[i] == s2[i] || s1[i] + 32 == s2[i] || s1[i] - 32 == s2[i])))
return false;
}
return true;
}
priority_queue<int, vector<int>, greater<int> > q;
int num;
void dfs(int x, int cnt, int cnt0)
{
if (cnt != cnt0)
{
if ((selector[cnt][0] == '#' && element[x].hasId && strcmp(element[x].id, selector[cnt] + 1) == 0) ||
(selector[cnt][0] != '#' && labelEqual(element[x].label, selector[cnt])))
{
for (int i = head[x]; i != -1; i = nex[i])
{
int l = to[i];
dfs(l, cnt + 1, cnt0);
}
}
else
{
for (int i = head[x]; i != -1; i = nex[i])
{
int l = to[i];
dfs(l, cnt, cnt0);
}
}
}
else
{
if ((selector[cnt][0] == '#' && strcmp(element[x].id, selector[cnt] + 1) == 0) ||
(selector[cnt][0] != '#' && labelEqual(element[x].label, selector[cnt])))
{
q.push(x);
num ++;
}
for (int i = head[x]; i != -1; i = nex[i])
{
int l = to[i];
dfs(l, cnt, cnt0);
}
}
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
getchar();
stack<int> rootStack;
memset(head, -1, sizeof(head));
for (int i = 1, cnt = 0; i <= n; i++)
{
scanf("%[^\n]", line + 1);
getchar();
int dotNum = 0;
for (int j = 1; line[j] == '.'; j++)
{
dotNum ++;
}
element[i].lev = dotNum / 2;
if (!rootStack.empty())
{
while (element[rootStack.top()].lev >= dotNum / 2)
{
rootStack.pop();
}
int temp = rootStack.top();
to[cnt] = i;
nex[cnt] = head[temp];
head[temp] = cnt++;
}
rootStack.push(i);
sscanf(line + dotNum + 1, "%s", element[i].label);
if (line[dotNum + strlen(element[i].label) + 1] == ' ')
{
element[i].hasId = true;
sscanf(line + dotNum + strlen(element[i].label) + 3, "%s", element[i].id);
}
}
while (m--)
{
scanf("%[^\n]", line + 1);
getchar();
int iter = 1;
int cnt = 0;
while (true)
{
sscanf(line + iter, "%s", selector[++cnt]);
iter += strlen(selector[cnt]) + 1;
if (line[iter-1] == '\0')
break;
}
num = 0;
dfs(1, 1, cnt);
printf("%d", num);
while (num != 0)
{
printf(" %d", q.top());
q.pop();
num --;
}
printf("\n");
}
return 0;
}
CCF-CSP题解 201809-3 元素选择器的更多相关文章
- CCF(元素选择器:50分):字符串+模拟
元素选择器 201809-3 这里我只考虑了没有后代选择器的情况 #include<iostream> #include<cstdio> #include<cstring ...
- CCF CSP 201604-3 路径解析
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201604-3 路径解析 问题描述 在操作系统中,数据通常以文件的形式存储在文件系统中.文件系 ...
- CCF CSP 201412-2 Z字形扫描
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201412-2 Z字形扫描 问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫 ...
- CCF CSP 201703-3 Markdown
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-3 Markdown 问题描述 Markdown 是一种很流行的轻量级标记语言(l ...
- CCF CSP 201312-3 最大的矩形
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201312-3 最大的矩形 问题描述 在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i( ...
- CCF CSP 201609-3 炉石传说
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201609-3 炉石传说 问题描述 <炉石传说:魔兽英雄传>(Hearthston ...
- CCF CSP 201403-3 命令行选项
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201403-3 命令行选项 问题描述 请你写一个命令行分析程序,用以分析给定的命令行里包含哪些 ...
- CCF CSP 201709-4 通信网络
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201709-4 通信网络 问题描述 某国的军队由N个部门组成,为了提高安全性,部门之间建立了M ...
- CCF CSP 201409-3 字符串匹配
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201409-3 字符串匹配 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那 ...
- CCF CSP 201503-3 节日
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201503-3 节日 问题描述 有一类节日的日期并不是固定的,而是以“a月的第b个星期c”的形 ...
随机推荐
- mysql定时任务(event事件)
1.event事件 事件(event)是MySQL在相应的时刻调用的过程式数据库对象.一个事件可调用一次,也可周期性的启动,它由一个特定的线程来管理的,也就是所谓的“事件调度器” 事件和触发器类似,都 ...
- devicemapper存储驱动下镜像的存储
docker配置devicemapper存储驱动 #查看当前使用的存储驱动,默认为overlay docker info | grep -i storage #停止dockersystemctl st ...
- goroutiine同步/channel、互斥锁、读写锁、死锁/条件变量
1. Goroutine同步[数据同步] 为什么需要goroutine同步 gorotine同步概念.以及同步的几种方式 1.1 为什么需要goroutine同步 package main impor ...
- Oracle的pl/sql编程语言
学习笔记: ##pl/sql编程语言 * 简介: * pl/sql编程语言是对sql语言的扩展,使得sql语言具有过程化编程的特性. * pl/sql编程语言比 ...
- Java异常处理只有Try-Catch吗?
今天,我们将讨论一个非常重要的主题-Java 中的异常处理.尽管有时可能会对此主题进行过多的讨论,但并非每篇文章都包含有用且相关的信息. Java 中最常见的异常处理机制通常与 try-catch 块 ...
- Linux01机和Linux02机的切换 和秘钥的配置
先试一下 01机和02机是否可以切换成功 使用 ssh root@ip地址 输入密码 ifconfig查看ip是否正确 切换回01机 01机配置的秘钥 查看隐形文件 01机配置秘钥 输入 ssh-c ...
- asp.net core 从 3.0 到 3.1
asp.net core 从 3.0 到 3.1 Intro 今天 .net core 3.1 正式发布了,.net core 3.1 正式版已发布,3.1 主要是对 3.0 的 bug 修复,以及一 ...
- 【Android - 自定义View】之自定义可滚动的流式布局
首先来介绍一下这个自定义View: (1)这个自定义View的名称叫做 FlowLayout ,继承自ViewGroup类: (2)在这个自定义View中,用户可以放入所有继承自View类的视图,这个 ...
- 微信小程序——详细讲解页面传值(多种方法)
1.使用navigator的url带参传值 (1)在pageA页面有一个固定的值要传递到pageB页面,比如说一个固定的值user_id要传递给B <navigator url=".. ...
- Python文本转化语音模块大比拼,看看青铜与王者的差别!
文本转语音 如果把Python比喻成游戏中的一个英雄,你觉得它是谁?对于Dota老玩家来说,我会想到钢琴手卡尔!感觉Python和卡尔一样,除了生孩子什么都可以做的角色.日常生活中,我们会涉及到很多语 ...