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;
}


在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章