题目:
思路做法:
模拟题的代码比较长,而且要考虑的细节较多,能从头到尾写完就有一定的难度(对新手而言),这道题目思路还算清晰,主要是通过对输入的字符串做处理并构建树,然后对于查询再用树的遍历如dfs查找符合要求的结点。
可能有难度的地方在于如何构建树和多重查询时如何用dfs找到结点。其他的如字符串处理就算用笨方法也能将nm和id处理出来,但要注意字母大小写转换的方法。
通过计算小数点的数量可以知道当前行的层级,维护一个整形数组root,它记录对于当前结点而言,每一层(主要是上一层)的祖先节点。通过
r
o
o
t
[
p
c
n
t
/
2
−
1
]
root[pcnt/2-1]
root[pcnt/2−1]可以计算出父节点的值,父节点维护子节点的vector。
需要多层查找时,dfs深搜下去,这里主要用题目给的提示用贪心策略:多级的后代选择器在匹配时,可以采用贪心的策略:除最后一级外,前面的部分都可以尽量匹配层级小的元素,因此最后一级要多次匹配。
总结:
题目的很多地方都给出了数据的一些陷阱,比如字母大小写问题,测试用例必然有关于这个的,多层查找时要把nm全部小写。
代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <string.h>
using namespace std;
const int N = 1e2+20;
struct E{ // element元素
string nm, id;
vector<int> child; // 子元素行数
E(){}
E(string _nm, string _id)
:nm(_nm), id(_id){ child.clear(); }
}e[N];
int n, m, root[N], num, ans[N], cnt;
string s, str[N];
void dfs(int u, int depth, bool isID){
if(isID && e[u].id == str[depth] || !isID && e[u].nm == str[depth]){
depth++; // 找到一层,层数加1
}
if(depth > num){ // 全部找到
ans[cnt++] = u;
depth = num; // 继续找 根据题目提示,采用贪心
}
for(int i = 0; i < e[u].child.size(); ++i){
dfs(e[u].child[i], depth, str[depth][0] == '#');
}
}
int main(){
scanf("%d%d ", &n, &m);
memset(root, 0, sizeof(root));
for(int i = 1; i <= n; ++i){
getline(cin, s);
int pcnt = 0; // 缩进数
string nm = "", id = "";
bool isID = 0;
// ..xxx #xxx
for(int j = 0; j < s.size(); ++j){
if(s[j] == '.'){
pcnt++;
}else if(s[j] == ' '){ // 空格后的是id
isID = 1;
}else{
if(isID) id += s[j];
else nm += tolower(s[j]); // 大小写不敏感,全部转化为小写
}
}
if(pcnt/2-1 >= 0){
e[root[pcnt/2-1]].child.push_back(i); // 上一层更新孩子
}
root[pcnt/2] = i; // 更新根
e[i] = E(nm, id);
}
for(int i = 0; i < m; ++i){
getline(cin, s);
num = 0; str[num] = "";
for(int j = 0; j < s.size(); ++j){
if(s[j] == ' '){ // 要查询的不止一层
num++; str[num] = "";
}else{
str[num] += s[j];
}
}
for(int j = 0; j <= num; ++j){
if(str[j][0] != '#'){
for(int k = 0; k < str[j].size(); ++k){
str[j][k] = tolower(str[j][k]);
}
}
}
cnt = 0; // 初始化
if(num == 0){ // 只有1个
if(str[num][0] == '#'){ // 查询id
for(int j = 1; j <= n; ++j){
if(e[j].id == str[num]) ans[cnt++] = j;
}
}else{ // 查询nm
for(int j = 1; j <= n; ++j){
if(e[j].nm == str[num]) ans[cnt++] = j;
}
}
}else{ // 多于1个,用dfs查找
dfs(1, 0, str[0][0] == '#');
}
sort(ans, ans+cnt); // dfs可能ans顺序乱,从小到大排序
printf("%d", cnt);
for(int j = 0; j < cnt; ++j) printf(" %d", ans[j]);
printf("\n");
}
return 0;
}