csp201809-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

样例输出:

3 6 9 11
1 6
0
2 9 11
1 11

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

思路:

1.存储
根据题目描述,结构化文档包括标签,id,等级,可以用vector存储,树形结构可以用parent指针反映。于是得出结构化文档的结构体包含这四个部分。
父亲指针指向最近的一个比该结点等级低的结点,先进后出,所以使用栈。
2.查询
将查询的字符串按空格分隔,存储在一个数组中,遍历库中所有结构体,贪心策略,结构化文档从后向前寻找父亲指针,要查询的字符串也在数组中从后向前遍历。
注意:不一定和直系父亲匹配,结构化文档可以一直想上寻找父亲,直到父亲结点为空或者字符串完全匹配。

代码:

#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <sstream>
using namespace std;
struct Node
{
	string tag;
	string id;
	int level;
	Node* par = NULL;
};
stack<Node*> s;
vector<Node*> vec;
void divide(const string&line, vector<string>&sel)
{
	string s;
	int i = 0;
	while(i < line.size())
	{
		if(line[i] != ' ')
			s += line[i];
		else{
			sel.push_back(s);
			s.clear();
		}
		i++;
	}
	sel.push_back(s);
}
bool check(Node* t, const string &s)
{
	if(s[0] == '#')//id 
		return t->id == s;
	else
	{
		if(t->tag.size() != s.size())return false;
		else{
			for(int i = 0; i < s.size(); i++)
			{
				if(tolower(t->tag[i]) != tolower(s[i])) return false;
			}
			return true;
		}
	}
}
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	string line;
	getline(cin, line);
	while(n--)
	{
		getline(cin, line);
		int i = 0;
		while(line[i] == '.')
			i+=2;//同时也是level 
		line = line.substr(i);//切割掉前面的 . 
		Node* now = new Node();
		now->level = i;
//		now.tag = line.substr(0, line.find(' '));//没找到空格返回一个特殊的值 这样不可以 
//		now.id = line.substr(line.find(' ')+1, line.size() - 1 - line.find(' '));
		stringstream ss(line);
		ss >> now->tag >> now->id;
		while(!s.empty() && s.top()->level >= i)
			s.pop();
		if(!s.empty())
			now->par = s.top();
		s.push(now);
		vec.push_back(now);
	}
	vector<string> vec_str;
	vector<int> ans;
	while(m--)
	{
		vec_str.clear();
		ans.clear();
		getline(cin, line);
		divide(line, vec_str);//按空格  拆分进vec_str 
		for(int i = 0; i < vec.size(); i++)
		{
			Node* t = vec[i];
			int idx = vec_str.size() - 1;
			if(check(t, vec_str[idx]))//第一个必须匹配 
			{
				t = t->par;
				idx--;
				while(t != NULL && idx >= 0)
				{
					if(check(t, vec_str[idx]))idx--;//可以不是 直接父辈匹配 
					t = t->par;
				}
				if(idx == -1)
					ans.push_back(i+1);
			}		
		}
		printf("%d ", ans.size());
		for(int i = 0; i < ans.size(); i++)
			printf("%d ", ans[i]);
		cout << endl;
	}
	return 0;	
} 

总结:

我感觉题目很难读懂,一大堆东西,对html,css也不是很熟,但是看了一下别人的博客,发现并没有太超出能力范围,但第一遍确实还是理解不到位。、
参考博客https://blog.csdn.net/IoT_fast/article/details/85016715?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值