题目要求写一个简易的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; }