做法
设置结构体数组保存文档元素,id属性,级数。每次读入一行,利用string的find()和substr()分割文档和选择器。关键在于如何匹配:如果只有一级选择器,直接遍历文档元素匹配即可(这里用vector保存结果),而多级的话,就从最末一级开始,每找到一个匹配的元素,就从这个元素向上遍历,依次匹配父级,都可以匹配的话就存入vector。(似乎是只要比当前元素高一级都算父级)
多级匹配采用从后往前(从子级到祖先级)匹配。刚开始想着从祖先级开始匹配,找到一个结果就保存,然后从这些结果中,找匹配的子集,直到找完所有级;非常非常麻烦。另外有几处代码比较相似,比如从空格处分割元素,将标签统一转换成小写等,可以通过函数实现,方便维护。
代码
#include<iostream>
#include<string>
#include<string.h>
#include<vector>
using namespace std;
vector<string> v;
vector<int> ans;
struct css
{
string id;
string lab;
int lev;//级数
}cs[109];
int main()
{
int n,m;
cin>>n>>m;
getchar();
for(int i=1;i<=n;i++)
{
string s;
getline(cin,s);
// cout<<s<<endl;
int len=s.size();
cs[i].lev=0;
for(int j=0;j<len;j++)
{
if(s[j]=='.'&&s[j+1]=='.')
{
j=j+1;
cs[i].lev++;
continue;
}
else
{
int t=s.find(' ',j);
if(t!=-1)
{
string s1;
s1.clear();
s1=s.substr(j,t-j);
if(s1[0]!='#')
{
for(int k=0;k<s1.size();k++)
{
if(s1[k]>=65&&s1[k]<=90)
{
s1[k]=s1[k]+32;
}
}
cs[i].lab=s1;
}
else
{
cs[i].id=s1;
}
j=t;
}
else
{
string s1;
s1.clear();
s1=s.substr(j,len-j);
if(s1[0]!='#')
{
for(int k=0;k<s1.size();k++)
{
if(s1[k]>=65&&s1[k]<=90)
{
s1[k]=s1[k]+32;
}
}
cs[i].lab=s1;
}
else
{
cs[i].id=s1;
}
break;
}
}
}
}
while(m--)
{
string s;
s.clear();
getline(cin,s);
int len=s.size();
ans.clear();
v.clear();
for(int i=0;i<len;i++)
{
int t=s.find(' ',i);
if(t!=-1)
{
string s1;
s1.clear();
s1=s.substr(i,t-i);
if(s1[0]!='#')
{
for(int j=0;j<s1.size();j++)
{
if(s1[j]>=65&&s1[j]<=90)
s1[j]=s1[j]+32;
}
}
v.push_back(s1);
i=t;
}
else
{
string s1;
s1.clear();
s1=s.substr(i,len-i);
if(s1[0]!='#')
{
for(int j=0;j<s1.size();j++)
{
if(s1[j]>=65&&s1[j]<=90)
s1[j]=s1[j]+32;
}
}
v.push_back(s1);
break;
}
}
int l1=v.size();
//cout<<l1<<endl;
for(int i=1;i<=n;i++)
{
if((v[l1-1][0]=='#'&&v[l1-1]==cs[i].id)||(v[l1-1][0]!='#'&&v[l1-1]==cs[i].lab))
{
if(l1==1)
ans.push_back(i);
else
{
int le=cs[i].lev;
int l2=v.size()-2;
for(int j=i-1;j>0;j--)
{
if(cs[j].lev==le-1)
{
if(v[l2]==cs[j].lab||v[l2]==cs[j].id)
l2--;
le=cs[j].lev;
if(l2<0)
{
ans.push_back(i);
break;
}
}
}
}
}
}
cout<<ans.size();
for(int j=0;j<ans.size();j++)
{
cout<<' '<<ans[j];
}
cout<<endl;
}
return 0;
}