问题描述
解题思路
根据题意可以知道在查询中可以分为两种情况
第一种是查询一个标签选择器或者id选择器(可以称为一级查询)
第二种就是存在大于两级的查询(可以称为多级查询)
显然第一种查询需要存储每一种元素在内容中所有出现的行,对应的数据结构可以是unordered_map< string, vector < int > >
对于第二种多级查询,例如查询所有满足 A B C D的位置
首先将所有D出现的位置找出来,也就是上面那个map中存的vector数组
遍历这个数组,相当于遍历每一条以D结尾的路径
对于每一条以D结尾的路径,从D开始回溯,每次回溯到当前行的父亲行(这里需要一个p数组记录父亲行的位置),并且如果路径中的该行中有元素与查询的最后一个元素匹配(这个匹配需要map来记录每一行有哪些元素,对应的数据结构可以是unordered_map < int, unordered_map < string, int > >),则查询元素弹出
当以D结尾的路径遍历完时,并且查询中的元素也为空,则说明这条路径能够满足查询,则将这个答案保存下来
至于p数组中的值,就是利用一个数组记录每一行之前最近的起始行就可以得到,具体可见代码,不难理解
至于两个map中的值,主要是利用双指针还有substr等函数,具体可见代码,不难理解
代码实现
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <unordered_map>
using namespace std;
const int N = 110;
vector <string> text;
int n, m;
int p[N];
unordered_map <string, vector <int>> val;
vector<vector <string>> query;
unordered_map <int, unordered_map<string, int>> value;
void workparent()
{
for (int i = 1; i <= n; i ++)
{
string str = text[i];
int j = 0;
while (j < str.size() && str[j] == '.') j ++;
text[i] = str.substr(j);
p[i] = j;
}
int t[N];
memset(t, 0, sizeof(t));
for (int i = 1; i <= n; i ++)
{
t[p[i]] = i;
if (p[i] == 0) continue;
int f = t[p[i] - 2];
p[i] = f;
}
}
void workquery()
{
for (int i = n + 1; i <= n + m; i ++)
{
string str = text[i];
vector <string> r;
for (int j = 0; j < str.size(); j ++)
{
int k = j;
string t;
while (k < str.size() && str[k] != ' ') t += str[k ++];
if (t[0] != '#') transform(t.begin(), t.end(), t.begin(), ::tolower);
r.push_back(t);
j = k;
}
query.push_back(r);
}
}
void workpos()
{
for (int i = 1; i <= n; i ++)
{
string str = text[i];
for (int j = 0; j < str.size(); j ++)
{
int k = j;
string t;
while (k < str.size() && str[k] != ' ') t += str[k ++];
if (t[0] != '#') transform(t.begin(), t.end(), t.begin(), ::tolower);
val[t].push_back(i);
value[i][t] = 1;
j = k;
}
}
}
int main()
{
cin >> n >> m;
getchar();
text.push_back("*");
for (int i = 0; i < n + m; i ++)
{
string str;
getline(cin, str);
text.push_back(str);
}
workparent();
workpos();
workquery();
for (int i = 0; i < query.size(); i ++)
{
vector <string> q = query[i];
vector <int> r = val[q.back()];
if (q.size() == 1)
{
cout << r.size();
for (auto x : r) cout << " " << x;
}
else
{
vector <int> res;
for (auto pathend : r)
{
vector <string> flag = q;
for (int row = pathend; row != 0 && !flag.empty(); row = p[row])
{
if (value[row][flag.back()]) flag.pop_back();
}
if (flag.empty()) res.push_back(pathend);
}
cout << res.size();
for (auto x : res) cout << " " << x;
}
cout << endl;
}
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)