思路就是根据题目的要求一步步模拟,比较简单,没有像别的博客一样建树,注释都在代码中,我认为需要注意的一点是标签的大小写不敏感。
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <unordered_map>
#include <map>
#include <vector>
using namespace std;
int main()
{
int n, m;
cin>>n>>m;
unordered_map<int, vector<string> > mp; //每一行到此行选择器的映射,第一个是标签选择器,第二个是ID选择器
unordered_map<int, int> prio; //每一行到此行深度的映射
getchar();
for(int i = 1 ; i <= n ; ++i)
{
string temp;
getline(cin, temp);
stringstream ss(temp);
string str1, str2;
ss>>str1; //首先处理标签选择器
int cnt = 0;
int j;
for(j = 0 ; j < str1.length() ; ++j)
{
if(str1[j] == '.') //统计'.'的个数,记录深度
cnt++;
else
break;
}
prio[i] = cnt;
string ID = "";
for(; j < str1.length() ; ++j)
ID += tolower(str1[j]); //将标签选择器全部置为小写,因为题上说大小写不敏感,这是一个坑点
mp[i].push_back(ID);
while(ss>>str2)
mp[i].push_back(str2); //将ID选择器存入map
}
for(int i = 0 ; i < m ; ++i)
{
string temp;
getline(cin, temp);
stringstream ss(temp);
string str;
vector<string> v;
while(ss>>str)
{
if(str[0] != '#') //如果不是标签选择器,那么处理
{
for(int j = 0 ; j < str.length() ; ++j)
str[j] = tolower(str[j]);
}
v.push_back(str);
}
bool flag = false;
vector<int> ans;
if(v.size() == 1) //如果只查一个,单独处理
{
for(int k = n ; k >= 1; --k)
{
for(int t = 0 ; t < mp[k].size() ; ++t)
{
if(mp[k][t] == v[0])
{
flag = true;
ans.push_back(k);
}
}
}
}
else
{
vector<int> st;
reverse(v.begin(), v.end()); //从最深处开始查
int cnt = 0;
int init = 0, prePrio = 0;
int flagNow = false; //看最深处的选择器是否存在
for(int k = n ; k >= 1 ; --k)
{
for(int t = 0 ; t < mp[k].size() ; ++t)
{
if(mp[k][t] == v[0])
{
flagNow = true;
st.push_back(k); //将最深处的选择器开始的位置记录下来
}
}
}
if(flagNow) //如果存在
{
for(int j = 0 ; j < st.size() ; ++j) //遍历这些最深处的选择器
{
// cout<<st[j]<<endl;
init = st[j]; //将最深处的选择器的位置设置为最终要存储的结果
prePrio = prio[st[j]]; //将深度初始化
cnt = 1; //将当前找到的选择器个数初始化
for(int k = st[j] - 1; k >= 1 ; --k) //从最深处开始从下往上寻找上一级的选择器
{
for(int t = 0 ; t < mp[k].size() ; ++t) //分别查询标签选择器和ID选择器
{
if(mp[k][t] == v[cnt]) //如果找到了
{
if(prio[k] < prePrio) //并且深度比下一级浅
{
// cout<<k<<endl;
prePrio = prio[k]; //那么重置深度,以便寻找上一级
cnt++;
if(cnt == v.size()) //如果此时已找到个数已经满足要求
{
ans.push_back(init);
flag = true;
cnt = 0;
goto now;
}
}
}
}
}
now:;
}
}
}
if(!flag)
cout<<0<<endl;
else
{
cout<<ans.size();
for(int j = ans.size() - 1 ; j >= 0 ; --j)
{
cout<<" "<<ans[j];
}
cout<<endl;
}
}
}
/*
11 5
html
..head
....title
..body
....h1
....p #subtitle
....div #main
......h2
......p #one
......div
........p #two
p
#subtitle
h3
body dIv #one p
Div div div p p p
*/