![](https://i-blog.csdnimg.cn/blog_migrate/fb0ae8fb1da01b957e5dc113f0bb1651.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a5370ca531c0bf6f326a85c638d94874.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6374c89c9c45fc4e528ced930bf39fe5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ca69292bd9f9d3679b9fe7658966b6ec.png)
思路:
复杂模拟题
采用结构体存储元素信息,输入时,统一化为大写或小写。
考虑三种元素选择器
标签/id选择器:
直接遍历整个数组 分别与label/id作比较即可
*后代选择器:
①.首先遍历一遍元素 找出符合最后一个条件的所有元素 放入一个vector中
②.对vector中的每个元素
首先判断倒数第二个条件
从该元素的上一行开始 如果找到满足条件的行 并且level 满足a[k].level<levels 说明当前满足条件
此时要将levels更新为a[k].level
接着判断倒数第三个条件
从上一次停下的位置开始
1 #include<iostream>
2 #include<algorithm>
3 #include<math.h>
4 #include<string>
5 #include<string.h>
6 #include<stdio.h>
7 #include<vector>
8 #include<map>
9 #include<sstream>
10 using namespace std;
11 int n,m,tnt;
12 struct node
13 {
14 string label;//标签 大小写不敏感 故可以全部转化为小写字母存储
15 string id;//id属性
16 int level;
17 }a[110];
18 string s;
19 //后代选择器用贪心的思路写
20 //吧记录祖先 改为记录后代
21 //并且记录后代时 需要划分后代的等级 因为需要贪心
22 int main()
23 {
24 cin>>n>>m;getchar();
25 int N=n,M=m;
26 while(N--)//将结构化文档初始读入 且记录前驱
27 {
28 tnt++;
29 getline(cin,s);
30 int levels=1,tmp=0;
31 while(tmp<s.length())
32 {
33 if(s[tmp]!='.'||s[tmp+1]!='.') break;
34 tmp+=2;
35 levels++;
36 }
37 a[tnt].level=levels;
38 int i=1;
39 int idx=s.find(' ');
40 if(idx!=s.npos)//label 和 id
41 {
42 a[tnt].label=s.substr(tmp,idx-tmp);
43 a[tnt].id=s.substr(idx+1,s.length()-(idx+1));
44 }
45 else a[tnt].label=s.substr(tmp,s.length()-tmp);
46
47 transform(a[tnt].label.begin(),a[tnt].label.end(),a[tnt].label.begin(),::tolower);
48 }
49
50 while(M--)
51 {
52 getline(cin,s);
53 int idx=s.rfind(' ',s.length()),last=s.length();
54 if(idx==-1)//说明是标签选择器或id选择器
55 {
56 vector<int> ans;
57 int tot=0;
58 if(s[0]=='#')//id选择器
59 {
60 for(int i=1;i<=n;i++)
61 {
62 if(a[i].id.compare(s)==0)
63 {
64 tot++;
65 ans.push_back(i);
66 }
67 }
68 cout<<tot<<" ";
69 for(auto &entry:ans) cout<<entry<<" ";
70 cout<<endl;
71 }
72 else//标签选择器
73 {
74 transform(s.begin(),s.end(),s.begin(),::tolower);
75 for(int i=1;i<=n;i++)
76 {
77 if(a[i].label.compare(s)==0)
78 {
79 tot++;
80 ans.push_back(i);
81 }
82 }
83 cout<<tot<<" ";
84 for(auto &entry:ans) cout<<entry<<" ";
85 cout<<endl;
86 }
87 }
88 else//后代选择器
89 {
90 vector<int> ans;
91 vector<string> limits;
92 stringstream ss(s);
93 while(ss>>s)
94 {limits.push_back(s);}
95 //先选择满足最后条件的
96 string tmp=limits.back();
97 if(tmp[0]=='#')
98 {
99 for(int i=1;i<=n;i++)
100 if(a[i].id.compare(tmp)==0) ans.push_back(i);//可能是答案的 我们先记录下来
101 }
102 else
103 {
104 transform(tmp.begin(),tmp.end(),tmp.begin(),::tolower);
105 for(int i=1;i<=n;i++)
106 if(a[i].label.compare(tmp)==0) ans.push_back(i);//可能是答案的 我们先记录下来
107 }
108
109 int ans_tnt=ans.size();
110 //处理前面的条件
111 for(int i=0;i<ans.size();i++)
112 {
113 int idx=ans[i],levels=a[idx].level,now=idx-1;
114 int tot=0;
115 for(int j=limits.size()-2;j>=0;j--)
116 {//从idx向前找 找到一个则更新初始的位置
117 for(int k=now;k>=0;k--)
118 {
119 if(limits[j][0]=='#')
120 {
121 if(a[k].id.compare(limits[j])==0&&a[k].level<levels)
122 {
123 tot++;
124 now=k-1;
125 levels=a[k].level;
126 break;
127 }
128 }
129 else
130 {
131 if(a[k].label.compare(limits[j])==0&&a[k].level<levels)
132 {
133 tot++;
134 now=k-1;
135 levels=a[k].level;
136 break;
137 }
138 }
139
140 }
141 }
142 if(tot!=limits.size()-1)
143 {
144 ans[i]=-1;
145 ans_tnt--;
146 }
147 }
148 cout<<ans_tnt<<" ";
149 for(auto &entry:ans)
150 if(entry!=-1) cout<<entry<<" ";
151 cout<<endl;
152 }
153
154 }
155 return 0;
156 }