201809-3

题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路

构建结构化文档:
使用结构体数组来记录结构化文档,结构体中包含label,id,自己的层次和父节点,父节点记录其父节点所在行,可将其作为索引直接找到父节点。
对结构化文档,每次读取一行,读取前面的“ . ”的数量,点的数量除以2当作其层次。对于第一行没有父节点且其前面没有点需要做特殊处理。
从vector最后的位置向前遍历,找到第一个层次数小1的即为父节点,记录下来。
通过前面是否有空格和“#”来区分是否为id,将label和id储存到vector中
查找:
若为单一的label或者是id查找,则只需要从头到尾遍历一遍就可以。如果符合,则存放到result中,最后输出总数量和每一个符合的行号。
若为多查找,则从尾反向遍历,如果找到符合得了,则根据该节点记录得父节点得行号直接跳跃。

代码

#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;
}



猜你喜欢

转载自blog.csdn.net/alicemh/article/details/106609359