题目
Sample Input
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
Sample Output
3 6 9 11
1 6
0
2 9 11
1 11
思路
使用结构体element记录每行的标签、id、缩进。由于每行中有空格,故使用getline(cin,s)读入一行。遍历s[i],给对应行的element赋值,当当前字符为’.‘时,缩进数加1;若为’ ',意味着开始读入标签,初始化标签为空字符;若标签读完后仍未到字符串的尾,继续读入id,初始化id为空。
接下来处理查询,使用vector< string >queue记录查询。将读入的一行查询按照空格分隔,赋给queue。
由于后代选择器是标签选择器和id选择器的综合,故只写一个函数用于处理后代选择器即可,标签选择器和id选择器为后代选择器只有一个查询的情况。接着从queue的最后一个查询开始,向前进行查询。每次查询需要匹配标签/id、缩进,故每次查询完成后需要更新下次查询的缩进和开始位置。
注意,若为标签,记得处理大小写转换。
代码
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
int n,m;
int const maxn=105;
struct element{
string label,id;
int level;
element(){}
element(string la,string i,int le){label=la;id=i;level=le;}
}e[maxn];
vector<string> query;
vector<int> ans;
void lower(string &s){
for(int i=0;i<s.length();i++)
if('A'<=s[i]&&s[i]<='Z')
s[i]=tolower(s[i]);
}
bool search(int &start,int& level,string s){
for(int i=start;i>=1;i--){
if(e[i].level<level){
level=e[i].level;
start=i;
if(s==e[i].id||s==e[i].label)
return true;
}
}
return false;
}
int main(){
cin>>n>>m;
string s;
getchar();
for(int i=1;i<=n;i++){
getline(cin,s);
int num=0;
while(s[num]=='.')
num++;
int le=num/2;
string la="";
while(num<s.length()&&s[num]!=' '){
la+=s[num];
num++;
}
lower(la);
string Id="";
if(num<s.length()){//有id
num++;
while(num<s.length()){
Id+=s[num];
num++;
}
}
e[i].label=la;e[i].id=Id;e[i].level=le;
// e.push_back(element(la,Id,le));
}
for(int i=0;i<m;i++)//读入m个查询
{
char tmp[100];
vector<string>query;//存储查询
vector<int>ans;//存储结果
gets(tmp);//读入
char *sp=strtok(tmp," ");//将插叙用空格分割,按序存放在query向量中
while(sp)
{
query.push_back(sp);
sp=strtok(NULL," ");
}
int len=query.size();
for(int j=0;j<len;j++)//将标签统一化成小写
if(query[j][0]!='#') lower(query[j]);
for(int j=1;j<=n;j++)//遍历n行元素
{
if(query[len-1]==e[j].id||query[len-1]==e[j].label)//最后一级选择器匹配了
{
int start=j,cnt=e[j].level,k=len-2;//使用search函数匹配各级父选择器
for(;k>=0;k--)
{
if(!search(start,cnt,query[k])) break;
}
if(k<0)//成功
ans.push_back(j);
}
}
//输出结果
cout<<ans.size();
for(int j=0;j<ans.size();j++)
cout<<" "<<ans[j];
cout<<endl;
}
return 0;
}