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

我的未来我决定 提交于 2019-11-27 12:30:23

题目要求写一个简易的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] != '\0'; 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("%[^\n]", 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("%[^\n]", 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] == '\0')
                break;
        }
        num = 0;
        dfs(1, 1, cnt);
        printf("%d", num);
        while (num != 0)
        {
            printf(" %d", q.top());
            q.pop();
            num --;
        }
        printf("\n");
    }

    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!