20180903(元素选择器) ccf-csp


题目

题目

分析

(这道题本来80分放了好久,要检查了重新写了judge,居然过了)
这道题卡80分卡了好久,是因为题目真的坑

  • 这道题的后代选择器是可以#id #id,我一开始以为id没有后代选择器
  • 这道题的后代选择器是元素和标签可以混合的,我第二开始以为一个选择器都是一样的标签(id) 题目说的是A`B均为标签选择器或者id选择器,这就很迷.
  • name大小写不敏感,而id大小写敏感,所以辨别的时候,name要全转化成小写(大写)
  • 后代选择器可以不是连续的,这个是真的坑,如下
    1
    …2
    …3
    那么1 3也是能找到的

真实分析

这道题我是看成一个树,每个节点有id,name,lev和parent.
构造树
大体思路就是第i行的数据存到nodes[i]里,这样我们找到索引就可以找到他的所有数据
在处理一行有空格的时候,我在搜索资料的时候发现了一种有趣的写法

#include<sstream>

	istringstream str(a);	
	string out;
	vector<string> p;
	while (str >> out) {
		p.push_back(out);
	}

他把字符像我们输电脑屏幕字符串一样,天然使用空格分离,很轻松就可以搞定.我在这里面也顺遍完成了name小写化(不用这个的话可能麻烦一点)
首先查看有多少个’.’,可以知道他是第几层(lev),对于如何寻找父节点,我们维护一个数组recent,这个数组里在每次一个node填进来的时候都更新,那么我们只要找到recent[lev-1]这个节点一定是他的父节点(recent里存的都是他每一级的祖宗)
为了方便找到节点,我们为id和name分别搞了一个map来通过id或者name来找到一个相应节点的额索引,由于name可能有多个,所以只是存一个vector的索引,具体内容存在vector里

由于我们构造树的时候是按照顺序的,所以我们的node,以及vec_name里的内容天然从小到大,寻找的思路大体上是先找到一个把手,就是最后一个节点,通过map找到的都是有嫌疑的,之后我们对照向前的每一个,寻找他的祖宗里有没有,直到找到html节点(标记nodes[1].parent=0),之后都对上的就是了

代码

#include<iostream>
#include<sstream>
#include<vector>
#include<string>
#include<map>
using namespace std;
const int nmax=1e3+10;
const int mmax=1e2+10;
int tot=0,tot_name=0;
int recent[100];
map<string,int> mp_id,mp_name;
vector<int> vec_name[nmax];
char line[100];
struct node{
	int parent;
	string name;
	string id;
	int lev;
	node(){}
	node(const node&w){parent=w.parent,name=w.name,id=w.id,lev=w.lev;}
	node(string a,string i,int p,int b):parent(p),name(a),id(i),lev(b){};
}nodes[nmax];
vector<string> split(string a){
	istringstream str(a);	
	string out;
	vector<string> p;
	while (str >> out) {
		if(out[0]!='#')
			for(int i=0;i<out.length();i++){
				out[i]=tolower(out[i]);
			}
		p.push_back(out);
	}
	return p;
}
void judge(){
	cin.getline(line,100);
	vector<int> ans,que;
	auto strr=split(line);
	int sze=strr.size(),pos;
	string tar=strr[sze-1];
	bool flag=true;
	if(tar[0]=='#')
	{
		if(mp_id.find(tar)==mp_id.end())
		{
			flag=false;
		}
		else
		{
			que.push_back(mp_id[tar]);
		}
	}
	else
	{
		if(mp_id.find(tar)==mp_name.end())
		{
			flag=false;
		}
		else
		{
			int index=mp_name[tar];
			for(int i=0;i<vec_name[index].size();i++)
			que.push_back(vec_name[index][i]);
		}
	}
	if(!flag){
		printf("0\n");return ;
	}
	for(auto it=que.begin();it!=que.end();it++){
		pos=*it;
		int ff=0;
		for(int i=sze-1;i>=0;i--)
		{
			while(pos!=0){
				if(nodes[pos].name==strr[i]||nodes[pos].id==strr[i]){
					ff++;
					pos=nodes[pos].parent;
					//cout<<pos<<endl;
					break;
				}
				else
				{
					pos=nodes[pos].parent;
				}
			}
		}
		if(ff==sze) ans.push_back(*it);
	}
	printf("%d",int(ans.size()));
	for(int i=0;i<ans.size();i++)
	{
		printf(" %d",ans[i]);
	}
}/*
void judge(){
	cin.getline(line,100);
	if(line[0]=='#'){
		string tmp(line);
		if(mp_id.find(tmp)!=mp_id.end())
			printf("1 %d",mp_id[tmp]);//连着#
		else printf("0");
	}
	else {
		vector<int> ans;
		auto vec=split(line);
		int sz=vec.size();
		int index=mp_name[vec[sz-1]];//last one
		//cout<<vec[sz-1]<<" "<<vec_name[index].size()<<endl;
		for(auto it=vec_name[index].begin();it!=vec_name[index].end();++it){
			bool flag=true;
			int pos=*it;
			for(int i=sz-1;i>=0;--i){
				string tt=vec[i];
				for(int i=0;i<tt.size();++i) tt[i]=tolower(tt[i]);
				if(tt!=nodes[pos].name) {
					//cout<<vec[i]<<"!="<<nodes[pos].name<<endl;
					flag=false;
					break;
				}
				if(nodes[pos].parent!=0)	pos=nodes[pos].parent;
				else {printf("error\n");}
			}
			if(flag) ans.push_back(*it);
		}
		printf("%d",ans.size());
		for(auto it=ans.begin();it!=ans.end();it++){
			printf(" %d",*it);
		}
	}
}*/
int main(){
	int num,j;scanf("%d%d",&num,&j);
	int pa;
	recent[0]=-1;
	getchar();
	for(int i=0;i<num;++i){
		cin.getline(line,100);
		auto vec=split(line);
		tot++;
		int pos=0;
		while(line[pos]=='.') ++pos;
		int level=pos/2;
		//
		string idd;
		if(vec.size()==2){//id
			idd=vec[1];
			mp_id[vec[1]]=tot;//连着#
		}
		string tmp=vec[0].substr(pos);
		if(mp_name.find(tmp)==mp_name.end()){//name
			mp_name[tmp]=++tot_name;
			//cout<<"tmp:"<<tmp<<"tot"<<tot_name<<endl;
		}

		int index=mp_name[tmp];
		vec_name[index].push_back(tot);
		//
		recent[level]=tot;
		if(level>=1) pa=recent[level-1];
		else pa=0;
		nodes[tot]=node(tmp,idd,pa,level);
		//cout<<tot<<" "<<vec[0]<<" "<<pa<<" "<<level<<endl;
	}
	//cout<<mp_name["p"]<<" "<<vec_name[mp_name["p"]].size();
	for(int i=0;i<j;++i){
		judge();
		printf("\n");
	}
	return 0;
}
/*
11 5
html
..head
....title
..body
....h1
....p #subtitle
....div #main
......h2
......p #one
......div
........p #two
p
#subtitle
h3
div p
div div p
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值