201809-3元素选择器

1.题意

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

在这里插入图片描述

2.解题思路

  1. 首先是存储问题,一开始我想用一个结构体存储它的父节点,子节点,标签,id,但是比较繁琐,并且n<100数据非常小,所以适合遍历搜索根据“.”的数量cnt,所以结构体中仅需存储标签,id,cnt,并且行号已经由vector下标记录了所以不用存行号。
  2. 读取数据问题,无论是文档还是查询都需要正行读入,这就用到了getchar(),getline(),gets()以及在对查询分id或标签时就要用到strtok()函数,返回一个指针,调用完需要将指针赋空,且指向分割符
  3. 关于选择器问题,可以根据提示找层次低的即自底向上遍历找符合条件的,同时应当注意到,无论是何种选择器,都是寻找标签或id匹配的,所以没有必要分开来讨论,只是后代选择器多找了几层
  4. 总结:一开始做题时,有很多地方不知道该怎样写,因为是树结构在考虑记录父子节点,但这不是算法题且数据很少不需要一下全部处理好,可以进行适当遍历寻找;还是要仔细读题和样例,不能误解题意;最后关于读数据以及分割数据,对string的操作还需要更加熟悉,需要及时复习关于string的相关知识点尤其是各种函数用法

3.AC代码

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring> 
using namespace std;
struct css{
	int cnt;
	string bq;
	string id;
	css(int b,string c,string d)
	{
		cnt=b;
		bq=c;
		id=d;
	}
};
vector<css>v;
bool search(int &start,string s)
{
	int cnt=v[start].cnt;
	for(int i=start;i>=0;i--)
	{
		if(v[i].cnt<cnt)
		{
			cnt=v[i].cnt,start=i;
			if(s==v[i].bq||s==v[i].id) return true;
		}
	}
	return false;
}
int main()
{
	int n,m,count,last;
	string str,bq,id;
	cin>>n>>m;
	getchar();//读取换行符 
	for(int i=0;i<n;i++)
	{
		getline(cin,str);
		bool flag=false;
		int cnt=0;
		bq="",id="";
		for(int j=0;j<str.size();j++)
		{
			if(str[j]=='.') cnt++;
			if(str[j]=='#'||flag==true) 
			{
				flag=true;
				id+=str[j];
			}
			if(str[j]!='.'&&str[j]!=' '&&flag==false)
			{
				bq+=str[j];
			}
		}
		for(int j=0;j<bq.size();j++)
		{
			bq[j]=tolower(bq[j]);
		}
		v.push_back(css(cnt,bq,id));
	}
	for(int i=0;i<m;i++)	
	{
		char tmp[100];
		vector<string>q;
		vector<int>ans;
		gets(tmp);
		char *p=strtok(tmp," ");
		while(p)
		{
			q.push_back(p);
			p=strtok(NULL," ");
		}
		for(int j=0;j<q.size();j++)
		{
			if(q[j][0]!='#')
			{
				for(int k=0;k<q[j].size();k++)
				{
					q[j][k]=tolower(q[j][k]);
				}
			}
		}
		int l=q.size();
		for(int j=0;j<n;j++)
		{
			if(q[l-1]==v[j].id||q[l-1]==v[j].bq)
			{
				int start=j,k=l-2;
				for(;k>=0;k--)
				{
					if(!search(start,q[k])) break;
				}
				if(k<0) ans.push_back(j+1);
			}
		}
		cout<<ans.size();
		for(int j=0;j<ans.size();j++)
		{
			cout<<" "<<ans[j];
		}
		cout<<endl;
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值