• CCF-CSP题解 201809-3 元素选择器


    题目要求写一个简易的CSS Selector。

    首先用结构体(<lev,label[],hasId,id[]>)存储元素。其中(lev)表示元素在html树中的深度(这个是因为逻辑凌乱才加上的

    接着用链式前向星存储html元素树。这里用一个栈(rootStack)方便找到新元素的父亲节点(temp)

    三种选择器都可以归结为第三种方式——后代选择器。

    题目里已经给了算法:在匹配时,可以采用贪心的策略,除最后一级外,前面的部分都可以尽量匹配层级小的元素。写个dfs就好了。

    注意标签不区分大小写,不可以直接用strcmp的。

    字符串处理有点不方便。要熟练掌握%s,%[^],getchar,fgets,sscanf及相关函数。

    #include <bits/stdc++.h>
    const int maxn = 100;
    const int maxm = 80; // max length of one element
    
    using namespace std;
    
    char line[maxm+10];
    
    struct tElement
    {
        int lev;
        char label[maxm+10];
        bool hasId;
        char id[maxm+10];
        tElement()
        {
            hasId = false;
        }
    };
    tElement element[maxn+10];
    
    int to[maxn+10];
    int nex[maxn+10];
    int head[maxn+10];
    
    char selector[maxm/2+10][maxm+10];
    
    bool labelEqual(char s1[], char s2[])
    {
        if (strlen(s1) != strlen(s2))
            return false;
        for (int i = 0; s1[i] != ''; i++)
        {
            if (!((s1[i] == s2[i] || s1[i] + 32 == s2[i] || s1[i] - 32 == s2[i])))
                return false;
        }
        return true;
    }
    
    priority_queue<int, vector<int>, greater<int> > q;
    int num;
    
    void dfs(int x, int cnt, int cnt0)
    {
        if (cnt != cnt0)
        {
            if ((selector[cnt][0] == '#' && element[x].hasId && strcmp(element[x].id, selector[cnt] + 1) == 0) ||
                (selector[cnt][0] != '#' && labelEqual(element[x].label, selector[cnt])))
            {
                for (int i = head[x]; i != -1; i = nex[i])
                {
                    int l = to[i];
                    dfs(l, cnt + 1, cnt0);
                }
            }
            else
            {
                for (int i = head[x]; i != -1; i = nex[i])
                {
                    int l = to[i];
                    dfs(l, cnt, cnt0);
                }
            }
        }
        else
        {
            if ((selector[cnt][0] == '#' && strcmp(element[x].id, selector[cnt] + 1) == 0) ||
                (selector[cnt][0] != '#' && labelEqual(element[x].label, selector[cnt])))
            {
                q.push(x);
                num ++;
            }
            for (int i = head[x]; i != -1; i = nex[i])
            {
                int l = to[i];
                dfs(l, cnt, cnt0);
            }
        }
    }
    
    int main()
    {
        int n, m;
        scanf("%d%d", &n, &m);
        getchar();
    
        stack<int> rootStack;
        memset(head, -1, sizeof(head));
        for (int i = 1, cnt = 0; i <= n; i++)
        {
            scanf("%[^
    ]", line + 1);
            getchar();
            int dotNum = 0;
            for (int j = 1; line[j] == '.'; j++)
            {
                dotNum ++;
            }
            element[i].lev = dotNum / 2;
            if (!rootStack.empty())
            {
                while (element[rootStack.top()].lev >= dotNum / 2)
                {
                    rootStack.pop();
                }
                int temp = rootStack.top();
                to[cnt] = i;
                nex[cnt] = head[temp];
                head[temp] = cnt++;
            }
            rootStack.push(i);
            sscanf(line + dotNum + 1, "%s", element[i].label);
            if (line[dotNum + strlen(element[i].label) + 1] == ' ')
            {
                element[i].hasId = true;
                sscanf(line + dotNum + strlen(element[i].label) + 3, "%s", element[i].id);
            }
        }
    
        while (m--)
        {
            scanf("%[^
    ]", line + 1);
            getchar();
            int iter = 1;
            int cnt = 0;
            while (true)
            {
                sscanf(line + iter, "%s", selector[++cnt]);
                iter += strlen(selector[cnt]) + 1;
                if (line[iter-1] == '')
                    break;
            }
            num = 0;
            dfs(1, 1, cnt);
            printf("%d", num);
            while (num != 0)
            {
                printf(" %d", q.top());
                q.pop();
                num --;
            }
            printf("
    ");
        }
    
        return 0;
    }
    
  • 相关阅读:
    javaScript中的find()方法和返回数据的内存指向
    高级函数 filter map reduce 的使用
    for ... in and for ... of 理解
    git 解决冲突问题
    H5内唤醒百度、高德APP
    HTML 5标准中最新引入的template标签介绍
    jquery选择器使用
    ajax封装函数
    常用正则表达式
    JS-----事件、image对象
  • 原文地址:https://www.cnblogs.com/acboyty/p/11363136.html
Copyright © 2020-2023  润新知