版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xbb224007/article/details/86550660
(一)题面:
(二)题意:
(中文题见题面)。
(三)题解:
其实一看到那个文档的表示方式,就很容易想到可以用一颗数来表示,查询时直接遍历树即可。
1、树结点:每个节点保存一行的标签和id属性,其结点编号为所在行号,即每行一个结点。
2、建树:这里建树可能有两个思路,一个是递归建树,即建树边输入,这个在实际的操可能比较麻烦(可能要回溯到很久以前的结点),另一个是插入式,即每输入一行将对应信息插入到对应的位置,这里考虑如何找到插入的位置:由于每一个结点编号都是一个行号,我们在插入某一个结点时,只要知道其前一级(最近的祖先元素)的那一行对应的行号(用一个数组进行保存和更新即可),然后遍历树找到对应结点,再插入到后面即可。
3、查询:对于非复合的查询直接遍历树的所有结点,判断结点信息是否满足查询,满足就保存编号。对于复合查询,我们遍历树的时候在路径上依次匹配,即按照提示的所说的贪心地去匹配即可,当除了最后一个之外全部匹配完以后,将后面的可以与最后一项匹配的结点编号全部保存即可。
实际上这两种操作再进行匹配时可以统一,具体见代码。
4、输出。
(四)代码:
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=201;
void norm_tag(string &s){ //标签全部变为小写
int l=s.length();
for(int i=0;i<l;i++)
if(s[i]>='A'&&s[i]<='Z')s[i]+=32;
}
struct tree_node{ //树的结点
string tag,id;
void init(string _tag,string _id){
tag=_tag;id=_id;norm_tag(tag);
}
};
struct Tree{
int level_info[maxn],nt; //level_info[i]表示当前层次为i的行号
vector<int>tree[maxn]; //存树
tree_node info[maxn]; //各个结点的具体信息
vector<int>ans; //最终结果
Tree(){nt=1;memset(level_info,0,sizeof level_info);}
void insert(string _tag,string _id,int lv,int rt,int pos){
//插入
if(rt==pos){ //找到了对应位置
tree[rt].push_back(nt);
info[nt].init(_tag,_id);
level_info[lv]=nt++;return; //更新信息
}
for(int i=0;i<tree[rt].size();i++)
insert(_tag,_id,lv,tree[rt][i],pos);
}
void query(string s[],int len,int rt,int pos){
//查询
if(s[pos]==info[rt].tag||s[pos]==info[rt].id){
//匹配
if(pos==len-1)ans.push_back(rt);
else pos++; //下一个
}
for(int i=0;i<tree[rt].size();i++)
query(s,len,tree[rt][i],pos);
}
void output(){
cout<<ans.size();
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++)
cout<<' '<<ans[i];cout<<'\n';
}
}solve;
int main(){
int n,m;cin>>n>>m;
string str;getchar();
for(int i=0;i<n;i++){
getline(cin,str);
int p1=str.find_first_not_of('.'),p2=str.find(' ');
int lv=p1/2+1,l=str.length();
string tg,id;
if(p2!=string::npos){
tg=str.substr(p1,p2-p1);
id=str.substr(p2+1,l);
}
else {tg=str.substr(p1,l);id="";}
solve.insert(tg,id,lv,0,solve.level_info[lv-1]);
}string s[101],ss;
for(int i=0,t=0;i<m;i++,t=0){
getline(cin,str);stringstream in(str);
while(in>>ss){
if(ss[0]!='#')norm_tag(ss);s[t++]=ss;
}
solve.ans.clear();solve.query(s,t,0,0);solve.output();
}
return 0;
}
(五)总结:
相对而言是比较简单的第三题了,但是当时想着递归建树...,然后一直没写出来。
也不一定见得要建树,实际上直接用数组去模拟也挺简单的,最后就这么写骗了点分。
当时有点写郁闷了,一直建不出树。