【模拟】元素选择器

问题描述

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

思路

本题的关键点是元素和id的存储和查询,由于查询有两种格式的数据,且要求元素大小写不敏感,所以要设计n*2数据存储每行数据的元素和id,且存储和查询的过程中用change把元素转化成小写。
由于元素查询有多级选择,在 n 2 n^2 n2的复杂度内考虑遍历所有行的元素或id,一旦等于后代选择器要求的最后一个元素,自底向上查看他的祖先是否含有选择器中的祖先序列,有则当前行元素或id满足,加入答案。由于我们只关心祖先元素,所以考虑用数组p来存储每一个祖先的行号。
那么如何处理结构化文档呢,可以采用栈的结构,对于新加入的元素,先弹出层级小于等于它的,保证栈中只含有它的祖先,此时栈顶元素就是它的父亲,更新p数组,可以保证已经弹出的元素p已经更新过。

有一个坑,不同元素的id值不同,注意审题。
模拟题为了优化代码,可以考虑使用各种stl或者其他优化。本题对于每一行的数据如何处理可以采用stringstream来分离元素和id(id可以为空),如何删除’…'可以采用string的substr或者char[]的strncpy(这个要提前清零)

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<map>
#include<stack>
#include<vector>
#include<sstream>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define mem(a,s) memset(a,s,sizeof(a))
typedef long long LL;
const int N = 100 + 5;
string s[N][2];
int p[N],n,m;
stack<pair<int, int> > st;
string change(string x){
    if(x[0]!='#')
        transform(x.begin(),x.end(),x.begin(),::tolower);
    return x;
}
bool find(int i,vector<string>& vec){
    int len = vec.size()-1;
    if(len==0)return true;
    len--;i = p[i];
    while(i){
        if((vec[len][0]=='#'&&vec[len]==s[i][1])
                ||(vec[len][0]!='#'&&vec[len]==s[i][0]))
            len--;
        if(len==-1)
            return true;
        i = p[i];
    }
    return false;
}
int main(){
//    freopen("in.txt","r",stdin);    
    cin>>n>>m;
    getchar();
    rep(i,1,n){
        char y[90],x[90];
        gets(y);
        int j = 0;
        while(y[j]=='.')j++;
        mem(x, 0);
        strncpy(x, y + j, strlen(y) - j);
        stringstream ss(x);
        ss >> s[i][0] >> s[i][1];
        s[i][0] = change(s[i][0]);
        while(!st.empty()&&st.top().second>=j)
            st.pop();
        if(!st.empty())
            p[i] = st.top().first;
        st.push({i, j});
    }
    vector<string> vec;
    vector<int> ans;
    while(m--){
        char x[90];
        vec.clear();
        ans.clear();
        gets(x);
        stringstream ss(x);
        string str;
        while(ss>>str)
            vec.push_back(change(str));
        int siz = vec.size();
        int idx = 0;
        if(vec[siz-1][0]=='#')
            idx = 1;
        rep(i, 1, n) if (s[i][idx] == vec[siz - 1] && find(i, vec))
            ans.push_back(i);
        cout << ans.size();
        for(auto it:ans)
            cout << ' ' << it;
        cout << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值