CCF-CSP201809-3 元素选择器

题目链接

问题描述

试题编号:201809-3
试题名称:元素选择器
时间限制:1.0s
内存限制:256.0MB
问题描述:




 

 

id选择器和标签选择器的查询都比较简单,稍微麻烦的是后代选择器。

我用了二维数组保存每个元素的祖先,第一维代表的是层级(冒号的个数除以2),第二维代表的是序号。

多级的后代选择器在匹配时,可以采用贪心的策略:除最后一级外,前面的部分都可以尽量匹配层级小的元素。

 

AC代码:

CSDN博客:https://blog.csdn.net/qq_40889820
#include<iostream>
#include<sstream>
#include<algorithm>
#include<string>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define e 2.71828182
#define Pi 3.141592654
using namespace std;
struct node
{
	vector<string> ance_lab[101];//标签祖先(父代) 
        vector<string> ance_id[101];//id祖先 (父代) 
	int col;//冒号个数 
	string label;//标签
	string id;//id属性 
}ele[101];//元素 
bool islegal(string a,string b)//两个标签是否相等(大小写不敏感) 
{
	if(a.length()!=b.length()) return false;
	for(int i=0;i<a.length();i++)
	if(a[i]==b[i]) continue;
	else if(a[i]==b[i]+'A'-'a') continue;
	else if(b[i]==a[i]+'A'-'a') continue;
	else return false;
	return true;
}
int main()
{
	int n,m;
	cin>>n>>m;
	getchar();
	for(int i=1;i<=n;i++)
	{
		string str;
		getline(cin,str);
		
		int num=str.find('.');
		while(str[num]=='.'||num==-1) num++;
		ele[i].col=num;//冒号个数 
		
		if(str.find('#')!=string::npos)//有id属性 
		{
			ele[i].id=str.substr(str.find('#')+1);
			ele[i].label=str.substr(num,str.find('#')-num-1);
		}
		else //无id属性 
		{
			ele[i].id="";
			ele[i].label=str.substr(num);
		} 
		
		//找祖先 
		for(int j=1;j<i;j++)
		{
			if(ele[j].col>=num) continue;
			int cnt=ele[j].col/2;
			if(ele[j].id!="")  ele[i].ance_id[cnt].push_back(ele[j].id);
			ele[i].ance_lab[cnt].push_back(ele[j].label);
			
		} 
	} 
	
	
	for(int i=1;i<=m;i++)
	{
		string sel;//selector
		getline(cin,sel);
		int ans=0,a[101];//查询结果 
		mem(a,0);
		if(sel.find('#')==string::npos&&sel.find(' ')==string::npos)//标签选择器查询 
		{
			for(int j=1;j<=n;j++)
				if(islegal(sel,ele[j].label))
				    a[++ans]=j;	
	                cout<<ans<<' ';
			for(int k=1;k<=ans;k++) cout<<a[k]<<' ';
			cout<<endl;	
		}
		
		else if(sel.find('#')!=string::npos&&sel.find(' ')==string::npos)//id选择器查询
		{
			sel=sel.substr(1);//去掉井号 
		        for(int j=1;j<=n;j++)
			    if(sel==ele[j].id)
				    a[++ans]=j;
			cout<<ans<<' ';
			for(int k=1;k<=ans;k++) cout<<a[k]<<' ';
			cout<<endl;	
		} 
		
		else //后代选择器 
		{
			string str;
			for(int j=1;j<=n;j++)
			{
			        //利用字符串流和栈将后代选择器的子代和父代按顺序区分出来 
			        stringstream ss(sel);
			        stack<string> temp;
			        int cnt=0;//子代和父代的总数 
			        while(ss>>str)
			        { 
			    	    temp.push(str);
			    	    cnt++;
			        }
			    
			        //子代是否满足条件 
			        str=temp.top();temp.pop();
				if(str.find('#')==string::npos&&!islegal(str,ele[j].label)) continue;
				else if(str.find('#')!=string::npos&&str.substr(1)!=ele[j].id) continue;

				//父代是否满足条件 
				int sum=0;//找到的父代个数 
				for(int p=(ele[j].col-2)/2;p>=0;p--)
				{
					str=temp.top();
					if(str.find('#')==string::npos) //标签 
					for(int q=0;q<ele[j].ance_lab[p].size();q++)
					{
					        if(islegal(str,ele[j].ance_lab[p][q])) 
					        {
						        sum++;
							temp.pop();
							break;
						}	
					}
					
					else //id
					for(int q=0;q<ele[j].ance_id[p].size();q++)
					{
						string stri=str.substr(1);//没讲#保存在id里,记得要将#去掉 
						if(stri==ele[j].ance_id[p][q]) 
					        {
						        sum++;
							temp.pop();
							break;
						}
					}   
					
					if(sum==cnt-1) 
					{
						a[++ans]=j;
						break;
					}
				}
					
			}
			cout<<ans<<' ';
			for(int k=1;k<=ans;k++) cout<<a[k]<<' ';
			cout<<endl;	
		}
	}
}
	

/*
11 5
html
..head
....title
..body
....h1
....p #subtitle
....div #main
......h2
......p #none
......div
........p #two
*/ 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值