元素选择器
问题分析
数据存储:
可以使用结构体实现,记录当前的层级,行,标签,ID。
数据输入:
因为一行中可能含有空格,使用getline(cin,s)输入字符串s,遍历字符串,找到第一个不是‘.’的位置和’#'的位置i1, i2。则层级=i1/2,标签=s[i1,i2-2],ID=s[i2,len-1]。
此处使用的是字符串的substr函数,注意如果有ID,则标签=s.substr(dot,kong-1-dot),如果是s.substr(dot,kong-dot),会把“ ”也放到标签字符串中,导致后面无法匹配。
查询的字符串的输入使用了istringstream,读到空格停止。将查询依次放入数组中。
查询:
多级后代选择器匹配时,除最后一级外,前面的部分都可以尽量匹配层级小的元素
由此要求,我们在查询时,先遍历数组,匹配查询的最后一个条件。若匹配到元素j,再从数组[0,j]匹配查询条件倒数第二级,若匹配到元素k,在从[0,k]匹配倒数条件第三级…以此类推,知道条件都匹配成功,则将j的行号记下来。最后输出即可。
代码实现
#include<iostream>
#include<cstring>
#include<string>
#include<sstream>
#include<vector>
#include<algorithm>
using namespace std;
struct node{
string lab;
string id;
int row;
int ceng;
};
bool search(node a[],int &start,int &cnt,string s)
{
for(int i=start;i>=1;i--)
{
if(a[i].ceng<cnt)
{
cnt=a[i].ceng,start=i;//保证a[i]是它的父亲,即第一个缩进小于它的元素
if(s==a[i].lab||s==a[i].id) return true;//成功
}
}
return false;
}
node a[105];
int main()
{
int n,m;
cin>>n>>m;
getchar();
for(int i=1; i<=n; i++)
{
string s;
getline(cin,s);
int dot=0;
for(;s[dot]=='.'; dot++){}
int kong=dot;
for(;s[kong]!='#'&&kong<s.size(); kong++){}
// cout<<dot<<" "<<kong<<endl;
a[i].ceng=dot/2;
a[i].row=i;
a[i].lab=s.substr(dot,kong-dot);
if(kong<s.size())
{
a[i].lab=s.substr(dot,kong-1-dot);
a[i].id=s.substr(kong);
}
else
a[i].id="";
transform(a[i].lab.begin(),a[i].lab.end(),a[i].lab.begin(),::tolower);
// cout<<a[i].id<<"\n"<<a[i].lab<<endl;
}
for(int i=1; i<=m; i++)
{
string ask[105];
int len=0;
string str;
getline(cin,str);
istringstream sss(str);
string ss;
while(sss>>ss)
{
if(ss[0]!='#')
transform(ss.begin(),ss.end(),ss.begin(), ::tolower);
ask[len]=ss;
len++;
}
int sum=0,ans[105];
for(int j=1; j<=n; j++)
{
if(a[j].id==ask[len-1] || a[j].lab==ask[len-1])
{
int rank=a[j].ceng;
int st=j;
int k=len-2;
for(; k>=0; k--)
{
if(search(a,st,rank,ask[k])==false)
break;
}
if(k<0)
{
ans[sum]=a[j].row;
sum++;
}
}
}
cout<<sum;
for(int j=0; j<sum; j++)
cout<<" "<<ans[j];
cout<<endl;
}
}