元素选择器 2018-09-3

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

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

分析:
是比较麻烦的一个题,首先每一行需要存储的内容是id,label,level ,其中level 用‘.’ 的个数除以2,id 和label 根据空格划分,label 的大小写不敏感,因此用transform(label.begin(),label.end(),label.begin(),::tolower);将label 全部转换成小写。
查询的时候,对于每一行数据仍然需要判断的是标签id 选择器,或者是后代选择器,用空格切分行的内容,存储在V 中,如果V.size()>1 则是后代选择器。
对于标签id 选择器,直接遍历即可,其中需要注意的是标签大小写不敏感,这时候再判断会比较麻烦,采用的方式是将V[0]中的内容复制一份,变成全小写id 用原数据判断,标签用全小写的判断。
对于后代选择器,从输入行的最后一个元素进行判断,对于匹配的每一行,向上搜索看是否满足条件,关键代码如下:

int num = arr[index].level,d = V.size()-2;
	for(int j=index-1;j>=0;--j)
	{	
		if(arr[j].level == num-1)
		{
			string t=V[d];
			transform(t.begin(),t.end(),t.begin(),::tolower);
			if((arr[j].id==V[d])||(arr[j].label==t))
				d--;
				
			if(d < 0)return true;
			num = arr[j].level;
		}
	}

代码:

//元素选择器 
#include<stdio.h>
#include<string>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
	 int level;//层数   //div 划分
	 string label;//标签
	 string id;//id	
	 node(int level,string label,string id)
	 :level(level),label(label),id(id){} 
	 node(){}  
};
node arr[101]; 
vector<string> V;
vector<int> A;
bool check(int index)
{
	int num = arr[index].level,d = V.size()-2;
	for(int j=index-1;j>=0;--j)
	{	
		if(arr[j].level == num-1)
		{
			string t=V[d];
			transform(t.begin(),t.end(),t.begin(),::tolower);
			if((arr[j].id==V[d])||(arr[j].label==t))
				d--;
				
			if(d < 0)return true;
			num = arr[j].level;
		}
	}
	return false;
}
int main()
{
	string line;
	int n,m;
  	cin>>n>>m;
  	getchar();
  	//int i,j,k;
 	int level;
  	string label,id;
  	for(int i=0;i<n;i++)
  	{
  	  	getline(cin,line);

  	  	int j=0;
  	  	while(j<line.length()&&line[j]=='.')
		{
			    j++;
		}
		level=j/2;   //用点划分层数 
		int k=line.find(' ',j+1);  //从下标j+1开始 找空格,有空格说明有id 选择器 
		if(k==-1)
		{
			 label=line.substr(j,line.length()-j);
			 id="";
		} 
		else
		{
			 label=line.substr(j,k-j);
			 id=line.substr(k+1,line.length()-k-1);
		}
		std::transform(label.begin(),label.end(),label.begin(),::tolower);
		arr[i]=node(level,label,id);
  	}  //输入处理完毕 
  string tmp;
  while(m--)
	{
		getline(cin,line);
  	 	int j=0;
  	 	int k=line.find(' ',j+1);  //判断是否是复合的   //div div p 
  	 	while(j<line.length())  
  	 	{
  	         if(k==-1)  
			 	k=line.length();
			 string temp=line.substr(j,k-j);  
			 V.push_back(temp);
			 j=k+1;         
			 k=line.find(' ',j+1);	                                         
	 	}   //将一行中的单词划分开 
	 	if(V.size()==1)
	 	{
	 		string t=V[0];
	 		transform(t.begin(),t.end(),t.begin(),::tolower);
	 		for(int i=0;i<n;i++)
	  	  	{
	  	  	  	if((arr[i].id==V[0])||(arr[i].label==t)) 
	  	  	  	{
	  	  	  	 	A.push_back(i);
			  	}
		  	}
		}
		else if(V.size()>1){
			int size = V.size();
			for(int j=0;j<n;j++)
			{
				string t=V[size-1];
				transform(t.begin(),t.end(),t.begin(),::tolower);
				if((arr[j].id==V[size-1])||(arr[j].label==t))
				{
					if(check(j))A.push_back(j); 
				}	
			}
		}
		sort(A.begin(),A.end());
		cout<<A.size();
        for(int j=0;j<A.size();j++)
            cout<<" "<<A[j]+1;   //输出
        cout<<endl;
        V.clear();
        A.clear();
	}
	return 0;	
} 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值