元素选择器
程序员文章站
2022-03-19 23:45:11
...
解题思路
- 本题将输入的每行字符串转换成特定的标签、id,进行相应操作即可
- 用结构体储存每个行,包括层级、父节点的行号、标签、id;用结构体数组存储所以行。
- 每次输入一行,用getline将其读入一个字符串,通过点的个数得到层级数,之后从当前数组中最后一个元素开始往上找它的父节点,即level比它小1的;之后通过判断#是否存在来判断之后读入数据的类型,如果是标签则全部转换为小写(因为大小写不敏感);得到了当前行的结构体的四个元素的值,将其插入数组。
- 每次输入选择器,用getline读入,通过空格看是否有多级(找空格的位置),如果没有空格则是前两种单一选择器,通过首位是否为#判断类型。遍历搜索,输出对应行数即可。
- 如果是多级选择器(空格找到),用空格作为分解符,每次通过每个段的首元素是否为‘#’判断类型,把每个段存储到数组中,倒序查找,每找到一个后循环把前一个和他的父节点比较,都相同则记录。最后输出即可。
完整代码
#include <iostream>
#include <vector>
using namespace std;
#include <cctype>
struct html
{
int level;//层级
int father;//父结点行号
string label;
string id;
};
vector<html> doc;//文档向量
vector<int> num;//结果向量
int main(){
int n,m,fa,le;
cin>>n>>m;
getchar();
while(n--)
{//处理文档
string s,la,id;
getline(cin,s);
int lee = 0;
while(s[lee] == '.')
lee++;
le = lee / 2;//得到层级数
if(lee == 0 || !doc.size())
fa = -1 ;
else{
for(int i = doc.size() - 1;i >= 0;i--){
if(doc[i].level == le - 1)//从最后一个元素开始往上找它的父节点,即level小1的
{
fa = i;
break;
}
}
}
bool flag = false;//表示是否有属性
while(lee < s.size())//忽略空格
{
if(s[lee] == ' ')
{
lee++;
continue;
}
if(s[lee] == '#')
{
flag = true;//有属性
id += s[lee];
lee++;
continue;
}
if(flag) id += s[lee];
else la += tolower(s[lee]);//全部转换为小写,大小写不敏感
lee++;
}
doc.push_back({le,fa,la,id});
}
while(m--){//选择
string s;
getline(cin,s);
int p = 0;
while(p != s.size() - 1 && s[p] != ' ') //通过空格看是否有二重
p++;
if(p == s.size() - 1)
{//单一选择器
if(s[0] == '#')//id选择器
{
for(int i = 0;i < doc.size();i++){
if(s == doc[i].id) num.push_back(i+1);
}
}
else//标签选择器
{
for(int i = 0;i < s.size();i++) s[i] = tolower(s[i]);
for(int i = 0;i < doc.size();i++){
if(s == doc[i].label) num.push_back(i+1);
}
}
cout<<num.size()<<" ";
for(int i = 0;i < num.size();i++) cout<<num[i]<<" ";
}
else//二重
{
int j = 0;
vector<string> v;
p = 0;
bool flag = true;
while(p < s.size()){
if(s[p] == '#') flag = false;
if(s[p] == ' ')//第二个
{
flag = true;//还原标志变量
v.push_back(s.substr(j,p-j));//各个层插入
j = p + 1;
}
if(flag)//id选择器,不区分大小写
s[p] = tolower(s[p]);//转为小写
p++;
}
v.push_back(s.substr(j,p-j));
for(int i = doc.size() - 1;i > 0;i--)//遍历
{
int q = v.size() - 1;
if(v[q] != doc[i].label && v[q] != doc[i].id)//啥也不是
continue;
p = doc[i].father,q--;
while(q >= 0 && p >= 0){
if(doc[p].label == v[q] || doc[p].id == v[q]) q--;
p = doc[p].father;
}
if(q == -1) num.push_back(i+1);
}
cout<<num.size()<<" ";
for(int i = num.size()-1;i >= 0;i--) cout<<num[i]<<" ";
}
cout<<endl;
num.clear();
}
return 0;
}
上一篇: PHP随机生成用户名和随机密码
下一篇: 聊聊新发布的iphone12