元素选择器
题目见CCF20180903
思想:
存储用自定义的类的数组,每个类中有属性name(文档的标签)、character(文档的属性id)、level(文档的层数,在输入时每有两个小数点level就多1)和father(文档的上一个父文档,这样可以快速地找到所有文档的上一文档)
再寻找结果数时,顺序查找类数组并且用队列来存储可能的结果位置,这样可以保证输出时位置数是从小到大的。
对于开头不是 # 且没有空格的行,即为标签选择器,只需要逐一匹配标签相等的类即可(注意标签相等是大小写不敏感的)
对于开头是 # 且没有空格的行,即为 id 选择器,逐一匹配 id 相等的类即可 (注意大小写敏感)
否则就为后代选择器,此时将该行前面的用空格隔开来的前代的特征用stack存储起来,以便后续从最终的子代向父代逐一进行匹配。clock表示前面应该要匹配的祖先节点的个数,留下最后一个作为最终的子代,依次遍历最终的子代的全部可能位置,然后使用father变量直接找到其上一级的节点,如果符合stack中存储的就继续,并且将stack pop()操作一次,clock变量减1;否则继续找其father。如果一直找祖先找到-1处(第一个类的祖先设为-1)仍旧没有匹配完,该条匹配失败,否则,该最终子代位置加入结果队列。
代码:
#include <iostream>
#include <stdio.h>
#include <queue>
#include <stack>
using namespace std;
int n,m;
queue<int> dui;
string ancestors[100];
int th;
class node
{
public:
string name;
string character;
int level;
int father;
};
node files[102];
void out()
{
for(int i=1;i<=n;i++)
{
cout<<files[i].name<<" "<<files[i].character<<" "<<files[i].level<<" "<<files[i].father<<endl;
}
}
bool deng(string a,string b)
{
if(a.length()!=b.length()) return false;
for(int i=0;i<a.length();i++)
if(a[i]==b[i]) continue;
else if(a[i]==b[i]+'A'-'a') continue;
else if(b[i]==a[i]+'A'-'a') continue;
else return false;
return true;
}
node create(string name,string character,int level,int father)
{
node change;
change.name=name;
change.character=character;
change.level=level;
change.father=father;
return change;
}
int main()
{
int former;
int level;
int father;
string a;
string name;
string character;
int length,one;
cin>>n>>m;
getchar();
for(int i=1;i<=n;i++)
{
getline(cin,a);
length=0;
father=-1;
while(a[length]=='.')
{
length+=2;
}
level=length/2;
one=a.find('#');
if(one!=string::npos)
{
character=a.substr(one+1);
name=a.substr(length,one-length-1);
}
else
{
character=" ";
name=a.substr(length);
}
for(int now_one=i-1;now_one>0;now_one--)
{
if(files[now_one].level==level-1)
{
father=now_one;
break;
}
}
files[i]=create(name,character,level,father);
}
//out();
for(int i=0;i<m;i++)
{
getline(cin,a);
while(dui.size())
{
dui.pop();
}
if(a[0]=='#' && a.find(' ')==string::npos)//开头是#且后面没空格
{
a=a.substr(1);
for(int w=1;w<=n;w++)
{
if(files[w].character==a)
{
dui.push(w);
}
}
}
else if(a[0]!='#' && a.find(' ')==string::npos)
{
for(int w=1;w<=n;w++)
{
if(deng(files[w].name,a))
{
dui.push(w);
}
}
}
else
{
th=0;
while(true)
{
int blank=a.find_first_of(' ');
if(blank==string::npos) break;
ancestors[th]=a.substr(0,blank);
//cout<<" "<<ancestors[th]<<endl;
th++;
a=a.substr(blank+1);
}
for(int w=1;w<=n;w++)
{
if((a[0]!='#' && deng(files[w].name,a)) || (a[0]=='#' && files[w].character==a.substr(1) ))
//先找到最终元素
{
int qian=w;
int clock=th-1;
while(clock>=0)
{
qian=files[qian].father;
//cout<<"qian:"<<qian<<endl;
if(qian==-1)
{
clock=-2;
}
else if(ancestors[clock][0]!='#' && deng(files[qian].name,ancestors[clock]))
{
clock--;
}
else if(ancestors[clock][0]=='#' && files[qian].character==ancestors[clock].substr(1))
{
clock--;
}
}
if(clock==-1) dui.push(w);
}
}
}
printf("%d",dui.size());
while(dui.size())
{
printf(" %d",dui.front());
dui.pop();
}
printf("\n");
}
}