CSP201809-3元素选择器

本文介绍了一种基于结构化文档的查询算法,通过定义结构体存储文档信息,使用贪心算法进行选择器匹配,实现对特定元素的有效定位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

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

思路
首先考虑数据的结构,用结构体存储结构化文档,每个结构体对象存储一行。结构体包含的内容有行号,级数,标签,id,并在结构体里定义构造函数用于对它初始化。

struct Elem {
	int row;
	int level;
	string label;
	string id;
	Elem(int row, int level, string label, string id) :
		row(row), level(level), label(label), id(id) {};
	Elem() {};
};

用户每输入一行结构化文档,程序先求出此行文档的级数level,其实只要数一下有几个点,再除以二就是它的级数。用substr函数将label和id分离开,并且需要注意将label转换成小写(或大写),这是因为题目中要求label标签是大小写不敏感的。

用户输入完结构化文档后,再输入待查询的选择器,每输入一行后,都把此行中的每一个元素用substr函数分离开,再存到string类型的向量V中,此时也要注意将label全部转换成小写。

调用查询函数,注意使用贪心算法,也就是除了最后一级外,其余的都尽量匹配级数小的元素。这个地方刚开始没看明白,下面我举例说明一下贪心算法。
现在有如下的结构化文档:
div1
..div2
....div2
....div3
输入待查询的选择器为:div1 div2 div3
按照贪心算法,div2应该匹配到第二行,而不是第三行,因为第二行的层级数为1,第三行的层级数为2,程序的最终输出结果为1 4。如果不采用这种算法,那么程序最终的输出结果可能是0

源代码

// 元素选择器1.0.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include<bits/stdc++.h>
using namespace std;
struct Elem {
	int row;
	int level;
	string label;
	string id;
	Elem(int row, int level, string label, string id) :
		row(row), level(level), label(label), id(id) {};
	Elem() {};
};
Elem elem[100];
vector<string> V;
vector<int> A;
void solve(int n) {
	int mindex = -1;
	int mlevel = -1;
	for (int j = 0; j < V.size(); j++) {
		if (j == V.size() - 1) {	//如果是最后一级元素
			for (int k = mindex + 1; k < n; k++)
				if ((elem[k].label == V[j] || elem[k].id == V[j])&&elem[k].level>mlevel)
					A.push_back(k + 1);
		}
		else {	//如果不是最后一级元素,则采用贪心算法
			int i;
			for (i = mindex+1; i < n; i++) {
				if (elem[i].label == V[j] || elem[i].id == V[j]) {
					mindex = i;
					mlevel = elem[i].level;
					break;
				}
			}
			if (mindex != -1) {
				for (; i < n; i++) {
					if ((elem[i].label == V[j] || elem[i].id == V[j]) && elem[i].level < mlevel) {	//找到了层级更小的元素
						mlevel = elem[i].level;
						mindex = i;
					}
				}
			}
			else
				break;
		}
	}
}
int main()
{
	int n, m;
	cin >> n >> m;
	getchar();
	int row = 0, level = 0;
	string temp;
	string label, id;
	for (int i = 0; i < n; i++) {
		getline(cin,temp);
		int k = 0;
		while (k != -1) {
			k = temp.find('.', level);
			level++;
		}
		level--;
		k = temp.find(' ', level);
		if (k == -1) {
			label = temp.substr(level);
			id = "";
		}
		else {
			label = temp.substr(level, k - level);
			id = temp.substr(k + 1);
		}
		transform(label.begin(), label.end(), label.begin(), ::tolower);
		elem[i] = { i,level/2,label,id };		
	}
	for (int i = 0; i < m; i++) {
		string temp;
		getline(cin, temp);
		int k1 = 0;
		int k2 = 0;
		int j = 0;
		while (k1 != temp.size()) {
			k1 = temp.find(' ',k2);
			if (k1 == -1) {
				k1 = temp.size();	
			}
				string str = temp.substr(k2, k1 - k2);
				int k0 = str.find('#',0);
				if (k0 == -1)
					transform(str.begin(), str.end(), str.begin(), ::tolower);
				V.push_back(str);
			k2 = k1+1;
		}
		solve(n);
		cout << A.size();
		for (int j = 0; j < A.size(); j++)
			cout << " " << A[j];
		cout << endl;
		A.clear();
		V.clear();
	}
	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
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值