题目描述
题目分析
题目是说给定HTML的文件结构,然后查询给定ID选择器、标签选择器、后代选择器后,符合的相应的行。
首先读入每一行的层次,标签和id(如果有的话),进行大小写转换并存储,注意标签大小写不敏感,但是id大小写敏感。
然后对需要的查询进行切割,找到每一个符合项从后向前搜素,直到第一项符合为止,则是一次成功的匹配,将其记录。将所有记录输出即可。
HIT
本题也可以通过建树解决,思路简单但是实现较为复杂。对于模拟题来说,不要纠结于复杂度,再暴力基本都是够的;如果卡复杂度的模拟题,就算优化也多得不了几个分。
代码
#define _ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include <bits/stdc++.h>
using namespace std;
struct node
{
string label;
string id;
int level;
}a[109];
int main()
{
int n,m;
cin>>n>>m;
getchar();
for (int i = 0; i < n; i++)
{//存储每一行,从0开始
int cnt=0;//点的数量
char temp;
bool endd=false;//是否结尾
while ((temp = getchar())!='\n')
{
if(temp=='.')cnt++;
else if(temp=='#')
{
string s;
cin>>s;
getchar();
a[i].label=temp+s;
break;
}
else
{
a[i].id+=tolower(temp);
while ((temp=getchar())!=' ')
{
if(temp=='\n')
{
endd=true;
break;
}
a[i].id+=tolower(temp);
}
}
if(endd)break;
}
a[i].level=cnt/2;//两个点为一组
}
for (int i = 0; i < m; i++)
{//m条查询
string cmd;
vector<int> ans;//每行的答案
ans.clear();
vector<string> str;//每次查询的分段
str.clear();
getline(cin,cmd);
int last=0;
for(int t=0;t<cmd.length();t++)//切割
if(cmd[t]==' ')
{
str.push_back(cmd.substr(last,t-last));
last=t+1;
}
str.push_back(cmd.substr(last,cmd.length()-last));
for (int j = 0; j < str.size(); j++)
{//大小写转换
if(str[j][0]=='#')continue;
for(int k=0;k<str[j].size();k++)
str[j][k]=tolower(str[j][k]);
}
if(str.size()==1)
{//单选择器
for(int k=0;k<n;k++)
if(a[k].id==str.front()||a[k].label==str.front())
ans.push_back(k);
}
else
{
for(int k=0;k<n;k++)
{
int ptr=str.size()-1;//后代选择器中最后一个
if(a[k].label==str[ptr]||a[k].id==str[ptr])
{
ptr--;
int lastt=0;
// for(int j=k-1;j>=0&&a[j].level<=a[k].level;j--)
for(int j=k-1;j>=0;j--)
{
if(a[j].level<a[k].level-lastt)
if(a[j].label==str[ptr]||a[j].id==str[ptr])
{
ptr--;
lastt++;
if(ptr==-1)break;
}
}
}
if(ptr==-1)ans.push_back(k);
}
}
cout<<ans.size()<<' ';
for (int t = 0; t < ans.size(); t++)cout<<ans[t]+1<<' ';
cout<<endl;
}
return 0;
}