CCF201809-3,元素选择器

嗯,也是折腾了一上午的题啊…好菜啊…其实就是普通的逻辑题,数据范围都很小根本不用担心超,就是把查询逻辑处理好久可以了

主要注意:

  • 标签大小写不敏感,id大小写敏感,会在一个测试点里集中测试,只有这个没注意能拿90分(我就在这卡了好久,直到看到一个人的答案才恍然大悟)
  • 标签和id是可以混合的,也就是可以 div #two p这样,我不清楚为什么说后代选择器A B均为xxxbalabala的,但实际上数据是混合的
  • 搜索的时候注意搜索的时候搜索到的标签之间一定有父子关系,同级元素是不能匹配两个搜索词的。
using namespace std;
#include<cstdio>
#include<string>
#include<list>
#include<stack>

struct xml{//元素的数据结构
    string name;
    string id;
    int parent;
    int lid;
    int level;
    void show(){
        printf("'%s' '%s' %d %d %d\n",name.c_str(),id.c_str(),parent,lid,level);
    }
};

int judgeLevel(string &s)//根据前面的两个点判断级别,用于确定元素级别和父亲元素
{
    int i=0;
    for(;i<s.size()&&s[i]=='.';i++){}
    return i/2;
}

xml x[101];

bool search(list<string> &keys,int right){
    //根据搜索关键词和初始位置从后往前搜索是否存在元素,是和具体的循环体配合的,因此多加了最尾元素的判断
    //如果第一个就匹配不了,直接退出
    list<string>::iterator cur = keys.end(),ini = keys.begin();//迭代器的应用
    cur--;//end指向空,因此要--才是尾元素
    if((*cur)!=x[right].id && (*cur)!=x[right].name)
    {
        //判断尾元素是否匹配,因为外端方法是循环向前遍历,如果从这里贪心就会多匹配一些元素
        return false;
    }
    cur--;
    ini--;//begin指向的是第一个元素,cur遍历到begin--时才会
    if(cur==ini)//如果迭代完了,说明全都匹配上了
    {
        return true;
    }
    right = x[right].parent;
    while(right>=0)
    {
        if((*cur) == x[right].id || (*cur) == x[right].name)
        {
            cur--;
            if(cur==ini)
            {
                return true;
            }
        }
        right = x[right].parent;//指向父亲,从父亲那开始继续匹配,这也是从尾往前匹配的原因,因为一个元素只可能有一个爸爸
    }
    return  false;
}

bool lower(string &a){
    //可以替换到下面的方法实现减少代码量
    //但替换后悔增加耗时和空间,具体原理不清楚
    //应该是方法传参的细节,也就是如果能少嵌套方法就尽量少嵌套
    for(int i = 0;i<a.size();i++)
    {
        if(a[i]>='A' && a[i]<='Z')
        {
            a[i] -= 'A'-'a';
        }
    }
}

int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    getchar();

    stack<xml> level;
    for(int i = 0;i<n;i++)
    {
        char cline[80];
        scanf("%[^\n]", &cline);getchar();

        string line = cline;
        int llevel = judgeLevel(line);
        int pos = line.find(' ');

        xml cur;
        if(pos!=-1)//有空格说明有标签和id
        {
            cur.name = line.substr(llevel*2,pos-llevel*2);
            for(int j = 0;j<cur.name.size();j++)//标签大小写不敏感
            {
                if(cur.name[j]>='A' && cur.name[j]<='Z')
                {
                    cur.name[j]-= 'A'-'a';
                }
            }
            cur.id = line.substr(pos+1,line.size()-pos);

        }else//没有说明..分级后是完整的标签
        {
            cur.name = line.substr(llevel*2,pos-llevel*2);
            for(int j = 0;j<cur.name.size();j++)
            {
                if(cur.name[j]>='A' && cur.name[j]<='Z')
                {
                    cur.name[j]-= 'A'-'a';
                }
            }
            cur.id = "";
        }
        cur.lid = i;
        cur.level=llevel;

        //分配父亲,仅在这里使用xml结构中的level属性
        //利用栈,栈的大小和级别刚好可以形成对应关系
        if(llevel==level.size())
        {
            if(level.empty())
            {
                cur.parent = -1;
                level.push(cur);
            }else{
                cur.parent = level.top().lid;
                level.push(cur);
            }
        }else if(llevel<level.size()){
            while(llevel != level.size())
            {
                level.pop();
            }

            if(level.empty())
            {
                cur.parent = -1;
                level.push(cur);
            }else{
                cur.parent = level.top().lid;
                level.push(cur);
            }
        }else{}//不可能大于

        x[i] = cur;
    }

    //接收查询词并处理
    for(int i = 0;i<m;i++)
    {
        list<string> keys;
        list<int> res;
        char ckey[80];
        char split;
        scanf("%s",ckey);
        split = getchar();

        string skey = ckey;
        skey = ckey;
        if(skey[0] != '#')
        {
            for(int j = 0;j<skey.size();j++)
            {
                if(skey[j]>='A' && skey[j]<='Z'){
                    skey[j] -= 'A'-'a';
                }
            }
        }
        keys.insert(keys.end(),skey);
        
        while(split == ' ')//分隔符是空格说明还有下一个,否则会接收到换行符
        {
            scanf("%s",ckey);
            skey = ckey;
            if(skey[0] != '#')
            {
                for(int j = 0;j<skey.size();j++)
                {
                    if(skey[j]>='A' && skey[j]<='Z'){
                        skey[j] -= 'A'-'a';
                    }
                }
            }
            keys.insert(keys.end(),skey);
            split = getchar();
        }

        //搜索
        int num = 0;
        int pos;
        for(int k = n-1;k>=0;k--)
        {
            pos = search(keys,k);
            if(pos)
            {
                res.insert(res.begin(),k+1);
                num++;
            }
        }

        //输出
        printf("%d ",num);
        for(list<int>::iterator iter = res.begin(),next;iter!=res.end();iter++)
        {
            next = iter;
            next++;
            if(next != res.end())
            {
                printf("%d ",*iter);
            }else
            {
                printf("%d",*iter);
            }
        }
        printf("\n");
    }

    return 0;
}

在这里插入图片描述

2019年9月3日第二次刷,更好的代码:

#include <bits/stdc++.h>
using namespace std;

struct css{
    int index;
    int parent;
    int level;
    string name;
    string id;
}e[102];

bool equal(css &ae,string &s){
    return ae.name == s || ae.id == s;
}
int n,m;

bool find(int cur,vector<string> &v){
    int p = 0;
    int i = cur;

    while(i>=0){
        if(equal(e[i],v[p])){
            p++;
        }else if(p == 0)//非常关键的一步判断
        {
            return false;
        }
        i = e[i].parent;
        if(p>v.size()-1) {
            return true;
        }
    }
    return false;
}


int main(){
    scanf("%d %d",&n,&m);

    stack<css> s;
    char block[2000];
    int level;
    char split;
    for(int i = 0;i<n;i++)
    {

        scanf("%*[.]%n",&level);
        scanf("%s%c",block,&split);
        for(int j = 0;block[j] != '\0';j++)
        {
            if(block[j]>='A' && block[j]<='Z'){
                block[j] -= ('A'-'a');
            }
        }
        level/=2;
        e[i].index = i;
        e[i].level = level;
        e[i].name = block;


        if(split == ' '){
            scanf("%s%*c",block);
            e[i].id = block;
        }
        while(!s.empty() && s.top().level>=e[i].level) {
            s.pop();
        }
        if(level == 0){
            e[i].parent = -1;
        }else{
            e[i].parent = s.top().index;
        }
        s.push(e[i]);
    }


    while(m--)
    {
        vector<string> v;
        split = ' ';
        while(split != '\n'){
            scanf("%s%c",block,&split);
            if(block[0] != '#'){
                for(int j = 0;block[j] != '\0';j++)
                {
                    if(block[j]>='A' && block[j]<='Z'){
                        block[j] -= ('A'-'a');
                    }
                }
            }

            v.insert(v.begin(),block);
        }

        vector<int> res;
        for(int i = n-1;i>=0;i--)
        {
            if(find(i,v)){
                res.insert(res.begin(),i+1);
            }
        }
        printf("%d ",res.size());
        for(int i = 0;i<res.size();i++)
        {
            printf("%d ",res[i]);
        }
        printf("\n");
    }




    return 0;
}


在这里插入图片描述

发布了132 篇原创文章 · 获赞 77 · 访问量 12万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览