题目背景
题目描述
输入输出
样例
Hints
解题思路
首先将每个元素处理为一个结构体node
- 包含4个属性:级数(用点数/ 2表示名次,名次越高点数越小)、元素标签label、元素id属性,以及该节点的父亲节点。
- 同时,对每个元素,结构体内编写选择器判定函数find(),和匹配函数nameIsSame(),对标签和id进行匹配。
当输入结构化文档的每个元素时
- 在查找label索引位置时,可通过索引位置判断’.'的数目,确定该行的级数
- 通过字符处理获得label和id(可没有id),且label标签名需要转为小写
- 若该行级数不大于当前父节点的级数,则父节点向上查找,直到找到级数更小的元素,作为此元素的父节点,每个新元素加入后,作为当前的父节点。
每个选择器输入过程中,若为后代选择器,要根据空格区分,依次加入选择器向量slt(标签选择器输入时要注意转换为小写)。
选择过程中,对每行元素依次判别,先对slt中最后一个字符串进行匹配,若不满足直接返回,判断下一个元素;若满足,根据向量中字符串的数目再判断该选择器的类型
- 若该选择器为标签选择器或id选择器,直接加入结果中
- 若为后代选择器,遍历文档依次查找该元素的父节点,判断父节点是否依次匹配slt向量前面字符串代表的标签或id,若向量中所有字符串全部匹配完毕,说明该元素满足次此选择器,加入结果
代码
#include<iostream>
#include<string>
#include<vector>
using namespace std;
struct node {
string label,id;
node *parent;
int line;
int level = -1;
bool nameIsSame(string &name) {
if (name[0]== '#') return name == id;
else return name == label;
}
void find(vector<string> &slt, vector<int> &lines_No) {
if (!nameIsSame(slt.back())) return;
int slt_index = slt.size() - 2;
node *p = this->parent;
while (p&&slt_index>=0) {
if (p->nameIsSame(slt[slt_index])) slt_index--;
p = p->parent;
}
if (path_index == -1) {
lines_No.push_back(line);
}
}
};
node *datas[100];
char s[100];
int main() {
int n, m;
cin>>n>>m;
getchar();
node *root = new node();
node *p = root;
for (int i = 0; i < n; ++i) {
getline(cin, s);
int label_index = 0;
char c;
while (c = s[label_index++]) {
if (c != '.') break;
}
int level = label_index / 2;
while (level <= p->level) p = p->parent;
string label;
label.push_back(c < 'a' ? c + 32 : c);//转换为小写
while (c = s[label_index++]) {
if (c == ' ') break;
label.push_back(c < 'a' ? c + 32: c);
}
string id;
while (c = s[label_index++]) {
id.push_back(c);
}
node *new_node = new node();
new_node->level = level;
new_node->line = i + 1;
new_node->label = label;
new_node->id = id;
new_node->parent = p;
datas[i] = new_node;
p = new_node;
}
for (int i = 0; i < m; ++i) {
vector<string> slt;
getline(cin,s);
int index = 0;
char c;
string tmp;
while (c = s[index++]) {
if (c == ' ') {
slt.push_back(tmp);//选择器加入vector
tmp = "";
}
else {
if (c=='#'||(tmp.size() > 0 && tmp[0]=='#')) //id大小写敏感
tmp.push_back(c);
else tmp.push_back(c < 'a' ? c + 32 : c);//label大小写不敏感
}
}
vector<int> lines_No;
slt.push_back(tmp);
for (int j = 0; j < n; ++j) {
datas[j]->find(slt, lines_No);
}
int len = lines_No.size();
cout << len;
for (int j = 0; j < len; ++j) {
cout << ' ' << lines_No[j];
}
cout << endl;
}
return 0;
}