201809-3 元素选择器
题目
思路
多级查询需要用到树形结构,详见代码。
AC代码如下
#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
struct node{//按行存文档(树形结构)
vector<int> child;
string name,id;
int level;//记录层次,用来找父亲节点
}nd[105];
int n,m;
void get_text(int i){//输入第i行文档并分析
string line;
getline(cin,line);
int s=0;
int t=line.find("..",s);
nd[i].level=1;
while(t!=string::npos){
nd[i].level++;//每多两个'.'层数加一
s=t+2;
t=line.find("..",s);
}
t=line.find(" ",s);//有空格表示有id
if(t!=string::npos){
nd[i].id=line.substr(t+1,line.size()-t-1);
nd[i].name=line.substr(s,t-s);
}
else nd[i].name=line.substr(s,line.size()-s);
transform(nd[i].name.begin(),nd[i].name.end(),nd[i].name.begin(),::tolower);//标签名不区分大小写
for(int j=i-1;j>=1;j--){//找父亲节点,往回看,首个level比自己小的就是
if(nd[j].level<nd[i].level){
nd[j].child.push_back(i);
break;
}
}
}
bool Matched(string str,int x){//匹配
if(str[0]=='#'&&str==nd[x].id) return true;
if(str==nd[x].name) return true;
return false;
}
void search(set<int> &f,string str,int x){//dfs遍历森林,查找符合要求的子孙
for(int i=0;i<nd[x].child.size();i++){
int u=nd[x].child[i];
if(Matched(str,u)) f.insert(u);//匹配到了就放入下一级查询的根节点集合
search(f,str,u);
}
}
void solve(){
string str;
getline(cin,str);
int s=0;
int t=str.find(" ",s);
set<int> f[80];//f记录每一级符合要求的节点
int i=0;
f[0].insert(0);//0级为设为0,设为1的话会影响第一行的查询
nd[0].child.push_back(1);//0节点的孩子为1
while(t!=string::npos){
string temp=str.substr(s,t-s);
if(temp[0]!='#')
transform(temp.begin(),temp.end(),temp.begin(),::tolower);//转换为小写
for(set<int>::iterator it=f[i].begin();it!=f[i].end();it++)//从上一级找到的结果开始dfs查询
search(f[i+1],temp,*it);
i++;
s=t+1;
t=str.find(" ",s);
}
string temp=str.substr(s,str.size()-s);//最后一级
if(temp[0]!='#')
transform(temp.begin(),temp.end(),temp.begin(),::tolower);
for(set<int>::iterator it=f[i].begin();it!=f[i].end();it++)
search(f[i+1],temp,*it);
i++;
cout<<f[i].size();
for(set<int>::iterator it=f[i].begin();it!=f[i].end();it++)
cout<<" "<<*it;
cout<<endl;
}
int main(){
cin>>n>>m;
cin.get();
for(int i=1;i<=n;i++) get_text(i);
for(int i=0;i<m;i++) solve();
return 0;
}