201809-3 CSP认证 元素选择器 (详细解析-树形结构)

       题目大意:

              给一个html文档,每一行又  ".",标签,id组成,如果上一层的点是下一层点+2,中间还没有比上一层相等以及更少的语句,那么这就形成一个子语句,然后查询就是题目中说的了。

              首先各位有没有代码都读烂了的情况下,但是就是卡在80分的情况,我们先来看看这一句。

          后代选择器,A和B均为标签选择器或id选择器,这句话是有歧异的。

         如果你卡在80分,那么我们读到的题目一定是这样的(A和B均为标签选择器 )或者  (A和B均为id选择器)。

         而题目的意思是  (A为标签选择器或id选择器)  并且  (B为标签选择器或id选择器)(这不废话吗?你一共也就给了两种啊)

      解题步骤:

   1. 把所有读入的字符串都分割成一个结构体,包括  ( 点的个数   ,  id    ,标签 )
      三个部分后两者是string类型。

   2. 把所有的id , 标签映射成一个int类型的数字,也就是 map<string , int>mp,mp2。

   3. 使用映射好的map , 讲对应的行塞入相应的vector
      比如,第5行和第6行有 ”mznb“ 这个标签,那么
      就在要”mznb“这个对应的vector  push  5和6(标签用v1,id用v2)

   4. 建立父子关系,遍历整个字符串,然后前边第一个比他少俩点的就是他父亲。

   5. 查询,无论查询是标签选择器还是id选择器,我们全部按复合选择器处理。 
      先使用刚刚的两个vector中的一个,找到最后一个标签的位置
      比如html    div   p , 那么我们把所有标签为p的位置
      都使用代码中的check函数去跳父亲。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAXN = 10005;
struct node
{
    int id,len,num_d;
    string s,q,h;
}C[MAXN];
vector<int>v1[MAXN],v2[MAXN];
map<string,int>mp,mp2;
int tot,tot2;
int n,m;
int fa[MAXN];
void fun(int i)
{
    int num = 0;
    int len = (C[i].s).size();
    for(int j=0;j<len;j++){
        if(C[i].s[j] == '.')num++;
        else break;
    }
    C[i].num_d = num;
    int idx = -1;
    for(int j=0;j<len;j++){
        if(C[i].s[j] == '#')idx = j;
    }
    string k = "";
    if(idx != -1){
        for(int j=idx;j<len;j++){
            k += C[i].s[j];
        }
        //cout<<k<<endl;
        if(!mp2[k])mp2[k] = ++tot2;
        v2[mp2[k]].push_back(i);
    }
    C[i].h = k;
    k = "";
    for(int j =0;j<len;j++){
        if(C[i].s[j] == '.')continue;
        if(C[i].s[j] == ' ')break;
        if(C[i].s[j]>='A' && C[i].s[j]<='Z')C[i].s[j] = C[i].s[j]-'A'+'a';
        k += C[i].s[j];
    }
    C[i].q = k;
    if(!mp[k])mp[k] = ++tot;
    v1[mp[k]].push_back(i);
}

string cx[MAXN];
vector<int>ans;
int tot_q = 0;
bool check(int x,int flag)
{
    int now = tot_q;
    int now_id = x;
    while(now>=1&&now_id!=0){
        if(C[now_id].q == cx[now] || C[now_id].h == cx[now]){
            now--;
        }
        now_id = fa[now_id];
    }
    return (now == 0);
}
int main()
{
    fa[1] = 0;
    scanf("%d%d",&n,&m);
    getchar();
    for(int i=1;i<=n;i++){
        getline(cin,C[i].s);
        C[i].len = (C[i].s).size();
        fun(i);
    }
    for(int i=n;i>=1;i--){
        int nd = C[i].num_d;
        for(int j=i-1;j>=1;j--){
            if(C[j].num_d == nd-2){
                fa[i] = j;
                break;
            }
        }
    }

    while(m--)
    {
        ans.clear();
        tot_q = 0;
        string q;
        getline(cin,q);
        string k = "";

        int len = q.size();
        for(int i=0;i<=len;i++){
            if(q[i] == ' ' ||  i == len){
                cx[++tot_q] = k;
                k = "";
            }
            else{
                k += q[i];
            }
        }
        bool f = 1;
        if(cx[tot_q][0] == '#')f = 0;
        for(int i=1;i<=tot_q;i++){
            if(cx[i][0] == '#')continue;
            int len =cx[i].size();
            for(int j=0;j<len;j++){
                if(cx[i][j]>='A' && cx[i][j]<='Z')
                    cx[i][j] = cx[i][j] - 'A' +'a';
            }
        }
        if(f){
            int id = mp[cx[tot_q]];
            int len = v1[id].size();
            for(int i=0;i<len;i++){
                int to = v1[id][i];
                if(check(to,1))ans.push_back(to);
            }
        }
        else{
            int id = mp2[cx[tot_q]];
            int len = v2[id].size();
            for(int i=0;i<len;i++){
                int to = v2[id][i];
                if(check(to,0))ans.push_back(to);
            }
        }
        int le = ans.size();
        cout<<le;
        for(int i=0;i<le;i++){
            cout<<" "<<ans[i];
        }
        cout<<endl;
    }
}

/*
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

11 90
html
..head
....title
..body
....h1
....p #subtitle
....div #main
......h2
......p #one
........p #two
..........p #two
#subtitle #two
#main #one #two
html head title
*/

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值