题目
样例
思路
模拟题,跟文件目录那个题目类似。复杂度稍微小一点点,不过也不简单,需要考虑的细节很多。
获取元素结构
根据空格获得层级
获得标识符
获得ID
保存元素
进行匹配
匹配类型选择
匹配id选择
心得
- 我尝试了存储成树和用模拟栈的方法来存储,最后发现还是用模拟栈的方法存储写起来比较快
- 树:每个元素只出现一次,通过指针进行连接
- 栈:每个元素都保存自己从根部来的路径,这样利于搜索匹配。速度慢一些,但数据量比较小,因此无需担心超时。
代码
#include <bits/stdc++.h>
using namespace std;
struct PROPERTY {
string label;
string id;
};
int n, m;
vector<vector<PROPERTY> > lines;//保存层级关系的枚举
vector<PROPERTY> cur;
void myget() {
string s;
getline(cin, s);//要处理空格,因此不能直接cin
int len = s.length();
int j = 0;
while (j < len && s[j] == '.') ++j;//统计前置空格个数
int level = j >> 1;//快速除法
PROPERTY pro;
int start = j;
while (j < len && s[j] != ' ') ++j;//统计非空格字符个数,也即标识符名称
pro.label = s.substr(start, j - start);
transform( pro.label .begin(), pro.label .end(), pro.label .begin(),::tolower);//小写
if (j < len) {//获取id
pro.id = s.substr(j + 1);
}
while (cur.size() > level) {//生成枚举
cur.pop_back();
}
cur.push_back(pro);//生成枚举
lines.push_back(cur);//一层枚举保存起来
}
void mysearch() {
string temp_line;
getline(cin, temp_line);
vector<string> selectors;
//处理选择器
for (int i = 0; i < temp_line.size();) {
int j = i;
while (++j < temp_line.size() && temp_line[j] != ' ');
string temp = temp_line.substr(i, j - i);
if (temp[0] != '#') {
for (int k = 0; k < temp.size(); ++k) {
temp[k] = tolower(temp[k]);
}
}
selectors.push_back(temp);
i = j + 1;
}
//进行选择
vector<int> results;
for (int k = 0; k < n; ++k) {//对每一个元素
int i = 0, j = 0;
while (i+1 < selectors.size()) {//判断层级匹配
while (j < lines[k].size()) {
if (lines[k][j].label == selectors[i] || lines[k][j].id == selectors[i]) {
break;
}
++j;
}
if (j == lines[k].size()) {
break;
}
++i, ++j;
}
if (i + 1 == selectors.size()) {
if (j == lines[k].size()) {
continue;
}
if (lines[k].back().label == selectors[i] || lines[k].back().id == selectors[i]) {//判断标签
results.push_back(k + 1);
}
}
}
cout << results.size();
for (int i = 0; i < results.size(); ++i) {
cout << " " << results[i];
}
cout << endl;
}
int main() {
cin >> n >> m;
getchar();
for (int k = 0; k < n; ++k) {
myget();
}
while (m--) {
mysearch();
}
return 0;
}