CCF CSP 201809-3 元素选择器

这题考验思路的清晰和对细节的把握;
刚开始不会写的时候翻了很多大佬们的代码,他们都说简单,萌新瑟瑟发抖…
在参考其它大佬们的代码时也发现了他们的一些bug,例如按题目中的样例,用h1 h2去测试的时候,有些博主的代码会输出1 8,但实际上这是一个树状结构,理应输出0,希望大家在参考其它大佬的代码时不要产生和我一样的疑惑^ _ ^

题目:

题目略长直接放链接了~
201809-3 元素选择器

思路:

1.定义结点的结构体,然后用树来存储整个结构化文档;
2.在处理label时注意忽略大小写,直接将所有label转成小写即可;
3.对于每一个查询,以空格为分隔,将所有子选择器倒序存放在数组中,然后dfs整颗树,在树中找数组中的第一个元素,找到了的话我们依次查找这个结点的祖先结点,去判断这个数组剩下的部分是否按序存在在它到根节点的路径中;
例如查询div div p,在数组中为{p,div,div},第11行的p到根节点的路径为p、div、div(#main)、body、html、root,显然该数组中的元素是该序列的一个子序列,所以第11行的p就符合;同理其它的p不符合条件;

代码:

#include<bits/stdc++.h>
using namespace std;
void tolwr(string & s){
	for(int i=0;i<s.length();i++) s[i]=tolower(s[i]);
}
struct tree{
	string label,id;
	int level;
	tree *parent;
	vector<tree *> chd;
	tree(){this->level=0;}
	tree(string label,string id,tree *parent,int level){
		this->label=label;this->id=id;
		this->parent=parent;this->level=level;
	}
};
vector<string> v;
int ans=0;
vector<int> rs;
void dfs(tree *p){
	if(p->label==v[0]||p->id==v[0]){
		tree *q=p->parent;
		int i;
		for(i=1;i<v.size()&&q->level;q=q->parent)
			if(q->label==v[i]||q->id==v[i]) i++;			
		if(i==v.size()){
			ans++;
			rs.push_back(p->level);
		}
	}
	for(auto e:p->chd) dfs(e);
}
int main(){
	int n,m;
	cin>>n>>m;
	getchar();
	tree *root=new tree();
	tree *p=root;
	int pre_pos=-3;
	for(int i=1;i<=n;i++){
		string name,label,id="";
		getline(cin,name);
		int label_pos=name.rfind('.');
		int id_pos=name.find('#');
		if(label_pos<0||label_pos>100) label_pos=-1;
		if(id_pos<0||id_pos>100) id_pos=name.length()+1;
		label=name.substr(label_pos+1,id_pos-label_pos-2);
		tolwr(label);
		if(id_pos<name.length()){
			id=name.substr(id_pos,name.length()-id_pos);
		}
		if(label_pos-pre_pos==4){
			pre_pos+=2;
			p=p->chd[p->chd.size()-1];
		}else if(label_pos<=pre_pos){
			for(int j=(pre_pos-label_pos)/2;j>=0;j--) p=p->parent;
			pre_pos=label_pos-2;
		}		
		tree *t=new tree(label,id,p,i);
		p->chd.push_back(t);
	}
	for(int i=0;i<m;i++){
		string query;
		getline(cin,query);
		v.clear();
		ans=0;
		rs.clear();
		for(int p=query.length()-1,q=p;p>=0;p--,q=p){
			while(query[p]!=' '&&p>=0) p--;
			string s=query.substr(p+1,q-p);
			if(s[0]!='#') tolwr(s);
			v.push_back(s);
		}
		dfs(root);
		cout<<ans;
		for(auto e:rs) cout<<' '<<e;
		putchar('
');
	}
	return 0;
}
原文地址:https://www.cnblogs.com/yuhan-blog/p/12308941.html