CSP201809-3 元素选择器

题目

题目链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Sample Input

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

Sample Output

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

思路

使用结构体element记录每行的标签、id、缩进。由于每行中有空格,故使用getline(cin,s)读入一行。遍历s[i],给对应行的element赋值,当当前字符为’.‘时,缩进数加1;若为’ ',意味着开始读入标签,初始化标签为空字符;若标签读完后仍未到字符串的尾,继续读入id,初始化id为空
接下来处理查询,使用vector< string >queue记录查询。将读入的一行查询按照空格分隔,赋给queue。
由于后代选择器是标签选择器和id选择器的综合,故只写一个函数用于处理后代选择器即可,标签选择器和id选择器为后代选择器只有一个查询的情况。接着从queue的最后一个查询开始,向前进行查询。每次查询需要匹配标签/id、缩进,故每次查询完成后需要更新下次查询的缩进和开始位置
注意,若为标签,记得处理大小写转换。

代码

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
int n,m;
int const maxn=105;
struct element{
    string label,id;
    int level;
    element(){}
    element(string la,string i,int le){label=la;id=i;level=le;}
}e[maxn];
vector<string> query;
vector<int> ans;

void lower(string &s){
    for(int i=0;i<s.length();i++)
        if('A'<=s[i]&&s[i]<='Z')
            s[i]=tolower(s[i]);
}

bool search(int &start,int& level,string s){
    for(int i=start;i>=1;i--){
        if(e[i].level<level){
            level=e[i].level;
            start=i;
            if(s==e[i].id||s==e[i].label)
                return true;
        }
    }
    return false;
}

int main(){
    cin>>n>>m;
    string s;
    getchar();
    for(int i=1;i<=n;i++){
        getline(cin,s);
        int num=0;
        while(s[num]=='.')
            num++;
        int le=num/2;
        string la="";
        while(num<s.length()&&s[num]!=' '){
            la+=s[num];
            num++;
        }
        lower(la);
        string Id="";
        if(num<s.length()){//有id
            num++;
            while(num<s.length()){
                Id+=s[num];
                num++;
            }
        }
        e[i].label=la;e[i].id=Id;e[i].level=le;
//        e.push_back(element(la,Id,le));
    }
    for(int i=0;i<m;i++)//读入m个查询
        {
            char tmp[100];
            vector<string>query;//存储查询
            vector<int>ans;//存储结果
            gets(tmp);//读入
            char *sp=strtok(tmp," ");//将插叙用空格分割,按序存放在query向量中
            while(sp)
            {
                query.push_back(sp);
                sp=strtok(NULL," ");
            }
            int len=query.size();
            for(int j=0;j<len;j++)//将标签统一化成小写
              if(query[j][0]!='#')  lower(query[j]);
            for(int j=1;j<=n;j++)//遍历n行元素
            {
                if(query[len-1]==e[j].id||query[len-1]==e[j].label)//最后一级选择器匹配了
                {
                    int start=j,cnt=e[j].level,k=len-2;//使用search函数匹配各级父选择器
                    for(;k>=0;k--)
                    {
                        if(!search(start,cnt,query[k])) break;
                    }
                    if(k<0)//成功
                      ans.push_back(j);
                }
            }
            //输出结果
            cout<<ans.size();
            for(int j=0;j<ans.size();j++)
              cout<<" "<<ans[j];
            cout<<endl;
        }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值