题目链接: oj
解题思路
这个题的最重要思路在于递归,每个表达式都为<操作符>(表达式 1)(表达式 2)
或者原子类型,但是表达式是可以嵌套的,举一个很复杂的例子:
&(&(3:1)(|(1:2)(2:3)))(|(&(2~5)(2~7))(2:5))
所以对于输入,我们先判断他是不是一个原子公式(也就是递归返回的部分),如果是原子公式就直接处理。如果是带操作符的,我们就递归获取表达式1和表达式2的结果,再根据操作符进行并集和交集运算即可。
记录一个新学到的函数lower_bound()是algorithm库的函数->找到范围内不小于目标值的第一个元素
AC代码
#include <bits/stdc++.h>
#include <stdlib.h>
using namespace std;
int m, n, ptr = 0;
string s;
vector<int> dn;
vector<vector<pair<int, int>>> attr;
// 返回一个字符串,获取一个单元(一串数字,符号,括号)
string getToken()
{
string buf = "";
// 是数字
if (s[ptr] <= '9' && s[ptr] >= '0')
{
while (s[ptr] <= '9' && s[ptr] >= '0')
{
buf += s[ptr];
ptr++;
}
}
else
{
buf += s[ptr];
ptr++;
}
return buf;
}
vector<int> calculate(vector<int> dnlist)
{
vector<int> ans;
string tk = getToken(); // 当前Token
if (tk[0] == '&' || tk[0] == '|')
{
char c = tk[0];
getToken(); // (
vector<int> res1 = calculate(dnlist);
getToken(); // )
getToken(); // (
if (c == '&')
{ // 与操作
ans = calculate(res1);
}
else
{ // 或操作
vector<int> res2 = calculate(dnlist);
for (int i : res2)
{
res1.insert(res1.end(), i);
}
sort(res1.begin(), res1.end());
ans.insert(ans.end(), res1.begin(), unique(res1.begin(), res1.end())); // 取交集
}
getToken(); // 最后还要跳过右括号
}
else
{ // 原子表达式
int key, value;
key = atoi(tk.data());
tk = getToken();
char sign = tk[0];
tk = getToken();
value = atoi(tk.data());
for (int i : dnlist)
{
auto a = lower_bound(attr[i].begin(), attr[i].end(), make_pair(key, 0));
// fail 没找到或者找到的不是key
if (a == attr[i].end()||(*a).first != key)
{
continue;
}
else
{
if ((sign == ':' && (*a).second == value) || (sign == '~' && (*a).second != value))
{
ans.push_back(i);
}
}
}
}
return ans;
}
int main()
{
vector<int> orilist;
scanf("%d", &n);
dn.resize(n);
attr.resize(n);
for (int i = 0; i < n; i++)
{
int num;
scanf("%d%d", &dn[i], &num);
attr[i].resize(num);
for (int j = 0; j < num; j++)
{
scanf("%d%d", &attr[i][j].first, &attr[i][j].second);
}
orilist.push_back(i);
}
scanf("%d", &m);
for (int i = 0; i < m; i++)
{
cin >> s;
ptr = 0;
vector<int> ans = calculate(orilist);
vector<int> print;
for (int j : ans)
{
print.push_back(dn[j]);
}
sort(print.begin(), print.end());
for (int j : print)
{
printf("%d ", j);
}
printf("\n");
}
return 0;
}