【CSP 201809-3 】 元素选择器
题目描述
输入格式![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b8af08f54a4f6ba49caf1d4b7b7e6ef5.png)
输出格式
参考样例
输入
11 5
html
..head
....title
..body
....h1
....p #subtitle
....div #main
......h2
......p #one
......div
........p #two
p
#subtitle
h3
div p
div div p
输出
3 6 9 11
1 6
0
2 9 11
1 11
解题思路
首先,定义一个Element结构体用来存放一个标签的信息(标记类型,标签所在的层级,标记的父节点编号,子节点编号vector容器)并用该结构体的数组来存放整个文档的信息。
然后,定义一个solve函数从一个节点开始搜索目标标签并将索引写入对应的vector中。
接着,在主函数中利用getline(cin,line);stringstream;读入一行数据,按空格进行切分数据,根据输入建立文档树。
最后,根据输入的查找内容输出结果。
(其中,对于后代迭代器采用贪心策略匹配,除了最后一级外前面部分尽可能匹配层级小的元素)
题目代码
#include<iostream>
#include<vector>
#include<string>
#include <algorithm>
#include <sstream>
using namespace std;
const int maxN=200;
struct Element{
string label,id;
int layer,father;
vector<int>Child;
}T,Doc[maxN];
vector<string>css[21];
vector<int>ans[21];
void solve(int i,int a,string c){
if(Doc[i].label==c||Doc[i].id==c){
ans[a].push_back(i+1);
}
for(int j=0;j<Doc[i].Child.size();j++){
solve(Doc[i].Child[j],a,c);
}
}
int main(){
int n,m,counter,father=0;
string line,temp,arg1,arg2;
vector<string> tokens;
cin>>n>>m;getchar();
for(int i=0;i<n;i++){
tokens.clear();
getline(cin,line);
stringstream ss(line);
while (ss >> temp)
tokens.push_back(temp);
arg1=tokens[0];
arg2="NULL";
if(tokens.size()==2)arg2=tokens[1];
counter=0;
while (arg1[0]=='.'){
arg1.erase(arg1.begin());
arg1.erase(arg1.begin());
counter+=1;
}
transform(arg1.begin(), arg1.end(), arg1.begin(), ::toupper);
Doc[i].label=arg1;
Doc[i].id=arg2;
Doc[i].layer=counter;
if(i==0){
Doc[0].father=0;
continue;
}
if(counter>Doc[father].layer){
Doc[father].Child.push_back(i);
Doc[i].father=father;
}
else{
while(counter<=Doc[father].layer)father=Doc[father].father;
Doc[father].Child.push_back(i);
Doc[i].father=father;
}
father=i;
}
Doc[0].father=-1;
for(int i=0;i<m;i++){
getline(cin,line);
stringstream ss2(line);
while (ss2 >>temp){
if(temp[0]!='#'){
transform(temp.begin(), temp.end(),temp.begin(), ::toupper);
}
css[i].push_back(temp);
}
if(css[i].size()==1){
solve(0,i,css[i][0]);
}
else{
bool judge=true;
int Index=0;
for(int j=0;j<css[i].size()-1;j++){
ans[20].clear();
solve(Index,20,css[i][j]);
if(ans[20].size()==0){judge=false;break;}
int max_layer=100000;
int o=0;
if(j!=0)o++;
for(;o<ans[20].size();o++){
if(max_layer>Doc[ans[20][o]].layer){
Index=ans[20][o]-1;
max_layer=Doc[ans[20][o]].layer;
}
}
}
if(judge==true){
solve(Index,i,css[i][css[i].size()-1]);
}
ans[20].clear();
solve(0,20,css[i][css[i].size()-1]);
for(int o=0;o<ans[20].size();o++){
int it=ans[20][o]-1;
bool judge=true,judge2;
int Layer=1000000000;
for(int l=int(css[i].size()-2);l>=0;l--){
int t=Doc[it].father;
judge2=false;
do{
if((Doc[t].label==css[i][l]||Doc[t].id==css[i][l])&&Layer>Doc[t].layer){
Layer=Doc[t].layer;
judge2=true;
break;
}
else{
t=Doc[t].father;
}
}while (t!=-1);
if(judge2==false){judge=false;break;}
}
if(judge)ans[i].push_back(ans[20][o]);
}
}
}
for(int i=0;i<m;i++){
sort(ans[i].begin(),ans[i].end());
cout<<ans[i].size();
for(int j=0;j<ans[i].size();j++){
cout<<" "<<ans[i][j];
}cout<<endl;
}
return 0;
}