201809-3-元素选择器

题意:

在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
思路:

题目很长,而且给的一开始的引入看的很吓人。然后通读后面的题目可以发现,即给定你一些文件的名字,有n个。然后有的可能有描述性的属性。同时每个这样的文件都会在前面的一个文件下,即为子节点。到了这里,感觉和目录管理器相似了。同时要注意其每个名字的label属性大小写不分,其中只包含有数字和字母。然后如果有描述性属性,则前面是以#开头。后面的m行则为查找的描述性信息。其中查找器分为三类,第一类是一个简单的label属性查找,第二类为简单的id属性查找,第三类则为多查找。

分析完题目开始进行题目的解析。首先是想到建树,但是后来尝试异常麻烦,特别是多查找的时候,需要反复从头遍历到整棵树,看看有没有这样的子节点。然后就用的数组模拟的,其中当然需要结构体。结构体中包含label,id两个属性。以及自己的层次和父节点。其中父节点记录其父节点所在行,即可使用这个来当作索引直接找到父节点。然后构建系统的时候,用了一个结构体的vector来保存所有的信息。每次读取一行,然后读取前面的“ . ”的数量,点的数量除以2即可当作其层次。这里要注意的是第一行html没有父节点,其他的可能也会有前面没有点的。故当作没有父节点。然后开始从vector最后的位置向前遍历,找到第一个层次数小1的即为父节点,记录下来。 接下来后面处理label和id,这里比较好处理,id前面有空格和“#”即可记录为有id。然后将这些信息储存好,放到vector中。然后接下来行需要查找的。如果是单一的label或者是id查找,则只需要从头到尾遍历一遍就可以。如果符合,则存放到result中,最后输出总数量和每一个符合的行号。如果是多查找的时候,则从尾反向遍历,因为子节点总是会在下面。如果找到符合得了,则根据该节点记录得父节点得行号直接跳跃就可以了。这题中自己觉得这个父节点得行号记录下来还是非常重要的。可以加速。查找也可以更方便了。然后讲一下题目中的巨坑的地方。一开始将label和id分开读,即根据题意是大概label完后面会更上一个空格然后#表示描述信息。然后一开始就先将label读完遇到空格之后就去读id。然后卡在60分,然后想到可能中间有空格的部分,于是变成遇到#就去读label还是卡在那。最后将两个放在一块读才过的。难道时有id 和label交叉输入的情况吗。。这也太残暴了。当然也可能是自己处理的问题。然后多级查找到的时候,按照题目的意思应该是要么多级的id要么多级的label,然后怎么都过不去,最后改了下两个混合的才过了。感觉这几次的坑都怪怪的。

代码:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

int n,m;
struct html{
	int level,father;  //父节点指向父亲所在的行 
	string label,id;
};
vector<html> Html; //存放每行的记录 
vector<int> result;  //存储要输出的结果 

char change(char t){
	if(t>=97) t-=32;
	return t;
}

int main(){
	cin>>n>>m;
	getchar();  //处理掉回车 
	while(n--){  
		int fa,level;   //分别记录父节点和行数 
		string s,label,id; 
		 
		getline(cin,s);
		int p = 0;   //记录点数 
		while(s[p] == '.')	p++;
		level = p / 2;  //层级数 
		if(p == 0 || !Html.size()){
			fa = -1	;  //没有父节点或者是第一个 
		}else{
			for(int i = Html.size() - 1;i >= 0;i--){
				if(Html[i].level == level - 1){ //找到其父节点的层数 
					fa = i;
					break;
				}
			}
		}
		
		int r = false;    
		while(p < s.size()){  //找出后面的label和id 
			if(s[p] == ' '){
				p++;
				continue;
			}
			if(s[p] == '#'){  //有描述信息id
				r = true;
				id += s[p];
				p++;
				continue;
			}
			if(r)	id += s[p];   //描述信息 
			else	label += change(s[p]);  //全部转化为小写 
			p++;
		}
		
		Html.push_back({level,fa,label,id}); 
	}
	
	 
	
	while(m--){  //读取查找的信息 
	    string s;
		getline(cin,s);
		int p = 0;
		while(p != s.size() - 1 && s[p] != ' ')	p++;
		if(p == s.size() - 1){//单一选择器
			if(s[0] == '#'){  //id特征查找 
				for(int i = 0;i < Html.size();i++){
					if(s == Html[i].id)	result.push_back(i+1);	
				}	
			}else{  //label,不区分大小写 
				for(int i = 0;i < s.size();i++){
					s[i] = change(s[i]);  	
				}		
				for(int i = 0;i < Html.size();i++){
					if(s == Html[i].label)	result.push_back(i+1);	 //找到 
				}
			}
			cout<<result.size()<<" ";
			for(int i = 0;i < result.size();i++)	cout<<result[i]<<" ";
		}else{  //多个查找 
			int j = 0;
			vector<string> v;
			p = 0;
			bool flag = true;
			while(p < s.size()){
				if(s[p] == '#')	flag = false;
				if(s[p] == ' '){ 
					flag = true; 
					v.push_back(s.substr(j,p-j));
					j = p + 1;
				}
				if(flag)	s[p] = change(s[p]);  //id不在意大小写,故全转换为小写 
				p++;
			}
			v.push_back(s.substr(j,p-j)); 
			
			for(int i = Html.size() - 1;i > 0;i--){  //父节点在上面  
				int q = v.size() - 1;  //要查找的文件的个数 
				if(v[q] != Html[i].label && v[q] != Html[i].id)	continue;
				
				p = Html[i].father; //找到,则直接去找其父节点 
				q--;   
				while(q >= 0 && p >= 0){ 
					if(Html[p].label == v[q] || Html[p].id == v[q])	q--;		
					p = Html[p].father;
				}
				if(q == -1)	result.push_back(i+1);  //说明找到 
			}
			cout<<result.size()<<" ";
			for(int i = result.size()-1;i >= 0;i--)	cout<<result[i]<<" "; 
		}
		cout<<endl;
		result.clear();
	}
	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值