题目描述
基本思路
过程及结构
问题解决方法过程及结构如下图所示
其中,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 |
int | st | 表示查询的起始位置,在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 | 依次存储每一级的选择器 |
int | n | 级数,及s数组元素个数 |
int | st | 表示查询的起始位置,在st行标签的子标签中查询 |
int | idx | 当前查询使用的选择器(标签或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
*/