CSP 201809-3 元素选择器(C++)

题目描述

在这里插入图片描述

基本思路

过程及结构

问题解决方法过程及结构如下图所示
在这里插入图片描述
其中,read负责读取层叠样式信息,read_query负责读取查询信息(读取一条处理一条),query负责处理一条查询信息,query_one负责处理元素标签选择器和id选择器,query_muti负责处理后代选择器。lwr可以将一个字符串中所有的大写字母变为小写,并返回。

基本信息存储方式

层叠样式信息存储在数组ele[2][1000]中,其中ele[0][i]表示第i行的标签名,ele[1][i]表示第i行的id(若不存在则为空字符串)。另外,第i行的级数(也就是第i行 ‘.’ 的数量除以2)存储在lv[i]中。

query_one 实现思路

该函数的参数如下表所示:

类型名称注释
string &s要查询的标签名或id
intst表示查询的起始位置,在st行标签的子标签中查询
int &resn用来统计符合要求的标签数量
int []lines用来存储所有符合要求标签的行号(从小到大升序存储)

该函数思路比较简单,只需从st+1行开始依次向下搜索,如果搜索到第i行,该行的级数lv[i]≥lv[st],说明已经找完了st行标签的所有子标签,查找完毕。

对于每一个子标签i(第i行的标签):

  • 如果s的第一个字符为’#’,那么判断ele[1][i]是否与s相等,相等则符合要求;
  • 如果s的第一个字符不为’#’,那么判断ele[0][i]是否与lwr(s)相等,相等则符合要求。

如果符合要求,那么将i存入lines[resn],resn加1。

最后返回是否找到了符合要求的标签(bool类型)。

query_muti 实现思路

该函数的参数如下表所示:

类型名称注释
string []s依次存储每一级的选择器
intn级数,及s数组元素个数
intst表示查询的起始位置,在st行标签的子标签中查询
intidx当前查询使用的选择器(标签或id)在s数组中的索引号
int &resn用来统计符合要求的标签数量
int []lines用来存储所有符合要求标签的行号(从小到大升序存储)

这个函数是一个递归函数。

如果当前要使用的选择器是数组中最后一个(idx == n-1),那么直接调用query_one进行查询,并将query_one的结果(是否找到)返回。

否则,从st+1行开始寻找是否有符合要求的子标签,遍历及查找方式与query_one相同。对于遍历到的一个符合要求的标签i,调用函数query_muti(s, n, i, idx+1, resn, lines),并记录返回值。若返回true,那么本函数执行结束,返回true,否则继续遍历。若一直未找到符合要求的子标签,返回false。

其他

lwr、query、read、read_query思路见源代码。利用query_one或query_muti处理后,最后按要求输出resn和lines即可。

完整代码

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int N, M;
string ele[2][1000];
int lv[1000];
string lwr(const string &s)
{
	string res;
	int d = 'A' - 'a';
	for(int i=0, l=s.length();i<l;i++)
	{
		if(s[i] >= 'A' && s[i] <= 'Z')	res.push_back(s[i]-d);
		else res.push_back(s[i]);  
	}
	return res;
} 
void read() //读取元素内容 
{
	lv[0] = -2;
	scanf("%d %d", &N, &M);	
	char c;
	int j;
	for(int i=0;i<=N;i++)
	{
		c = getchar();
		j=0;
		while(c != '\n')
		{
			if(c == '.')	lv[i]++;
			else if(c == ' ')	j++;
			else ele[j][i].push_back(c);
			c = getchar();
		}
		ele[0][i] = lwr(ele[0][i]);
		lv[i] /= 2; 
	}
}
bool query_one(string &s, int st, int &resn, int lines[])  //处理单级选择器 
{
	bool flag = false;
	for(int i=st+1;i<=N && lv[i] > lv[st];i++)
	{
		if(
			(s[0] == '#' && ele[1][i] == s)
			||
			(lwr(s) == ele[0][i])
		  )
		  {
		  	lines[resn++] = i;
		  	flag = true;
		  } 
	}
	return flag; 
} 

bool query_muti(string s[], int n, int st, int idx, int &resn, int lines[])   //处理多级选择器
{
	if(idx == n-1)	return query_one(s[idx], st, resn, lines);
	else
	{
		int lv0 = lv[st];
		for(int i=st+1; i<=N && lv[i]>lv0; i++)
		{
			if(
			(s[idx][0] == '#' && ele[1][i] == s[idx])
			||
			(lwr(s[idx]) == ele[0][i])
			)
			{
				if(query_muti(s, n, i, idx+1, resn, lines))	return true;
			}
		}
		return false;
	}
	
} 
void query(string s[], int n)    //负责处理所有选择器 
{
	int lines[1000];
	int resn=0;
	if(n == 1)	query_one(s[0], 0, resn, lines);
	else query_muti(s, n , 0, 0, resn, lines);
	printf("%d", resn);
	for(int i=0;i<resn;i++)	printf(" %d", lines[i]);
	printf("\n");
	
}

void read_query() //读取查询信息并查新 
{
	char c; 
	for(int i=0;i<M;i++)
	{
		string s[1000];
		int j=0;
		c = getchar();
		while(c != '\n')
		{
			if(c == ' ')	j++;
			else s[j].push_back(c);
			c = getchar();
		}
		j++;
		query(s, j);
	}
	
}
int main ()
{
	read();
	read_query(); 
	return 0;
} 
		
/*
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
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值