csp 201809-3 元素选择器

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

做法

设置结构体数组保存文档元素,id属性,级数。每次读入一行,利用string的find()和substr()分割文档和选择器。关键在于如何匹配:如果只有一级选择器,直接遍历文档元素匹配即可(这里用vector保存结果),而多级的话,就从最末一级开始,每找到一个匹配的元素,就从这个元素向上遍历,依次匹配父级,都可以匹配的话就存入vector。(似乎是只要比当前元素高一级都算父级)

多级匹配采用从后往前(从子级到祖先级)匹配。刚开始想着从祖先级开始匹配,找到一个结果就保存,然后从这些结果中,找匹配的子集,直到找完所有级;非常非常麻烦。另外有几处代码比较相似,比如从空格处分割元素,将标签统一转换成小写等,可以通过函数实现,方便维护。

代码

#include<iostream>
#include<string>
#include<string.h>
#include<vector>
using namespace std;

vector<string> v; 
vector<int> ans;

struct css	
{
	string id;
	string lab;
	int lev;//级数 
}cs[109];

int main()
{
	int n,m;
	cin>>n>>m;
	getchar();
	for(int i=1;i<=n;i++)
	{
		string s;
		getline(cin,s);
	//	cout<<s<<endl;
		int len=s.size();
		cs[i].lev=0;
		for(int j=0;j<len;j++)
		{
			if(s[j]=='.'&&s[j+1]=='.')
			{
				j=j+1;
				cs[i].lev++;
				continue;
			}
			else
			{
				int t=s.find(' ',j);
				if(t!=-1)
				{
					string s1;
					s1.clear();
					s1=s.substr(j,t-j);
					if(s1[0]!='#')
					{
						for(int k=0;k<s1.size();k++)
						{
							if(s1[k]>=65&&s1[k]<=90)
							{
								s1[k]=s1[k]+32;
							}
						}
						cs[i].lab=s1;
					}
					else
					{
						cs[i].id=s1;
					}
					j=t;	
				}
				else
				{
					string s1;
					s1.clear();
					s1=s.substr(j,len-j);
					if(s1[0]!='#')
					{
						for(int k=0;k<s1.size();k++)
						{
							if(s1[k]>=65&&s1[k]<=90)
							{
								s1[k]=s1[k]+32;
							}
						}
						cs[i].lab=s1;
					}
					else
					{
						cs[i].id=s1;
					}
					break;	
				}
			}
		}
	}
	while(m--)
	{
		string s;
		s.clear();
		getline(cin,s);
		int len=s.size();
		ans.clear();
		v.clear();
		for(int i=0;i<len;i++)
		{
			int t=s.find(' ',i);
			if(t!=-1)
			{
				string s1;
				s1.clear();
				s1=s.substr(i,t-i);
				if(s1[0]!='#')
				{
					for(int j=0;j<s1.size();j++)
					{
						if(s1[j]>=65&&s1[j]<=90)
					    s1[j]=s1[j]+32;
					}
				}
				v.push_back(s1);
				i=t;
			}
			else
			{
				string s1;
				s1.clear();
				s1=s.substr(i,len-i);
				if(s1[0]!='#')
				{
					for(int j=0;j<s1.size();j++)
					{
						if(s1[j]>=65&&s1[j]<=90)
					    s1[j]=s1[j]+32;
					}
				}
				v.push_back(s1);
				break;
			}
		}
		int l1=v.size();
		//cout<<l1<<endl;
		
		for(int i=1;i<=n;i++)
		{
			if((v[l1-1][0]=='#'&&v[l1-1]==cs[i].id)||(v[l1-1][0]!='#'&&v[l1-1]==cs[i].lab))
			{
				if(l1==1)
				ans.push_back(i);
				else
				{
					int le=cs[i].lev;
					int l2=v.size()-2;
					for(int j=i-1;j>0;j--)
					{
						if(cs[j].lev==le-1)
						{
							if(v[l2]==cs[j].lab||v[l2]==cs[j].id)
								l2--;
							le=cs[j].lev;
							if(l2<0)
							{
							   ans.push_back(i);
							   break;
						    }
						}
					}
				}
			}	
		}
		
		cout<<ans.size();
		for(int j=0;j<ans.size();j++)
		{
			cout<<' '<<ans[j];
		}
		cout<<endl;
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值