简化的LL1写法。
#include <bits/stdc++.h>
using namespace std;
struct user {
int id;
map<int, int> attributes;
};
struct expr {
virtual bool accept(const user& u) = 0;
};
struct assert_expr : public expr {
int attrid, attrval;
assert_expr(int id, int val) : attrid(id), attrval(val) {}
bool accept(const user& u) override {
return (u.attributes.count(attrid) && (u.attributes.at(attrid) == attrval));
}
};
struct nassert_expr : public expr {
int attrid, attrval;
nassert_expr(int id, int val) : attrid(id), attrval(val) {}
bool accept(const user& u) override {
return (u.attributes.count(attrid) && (u.attributes.at(attrid) != attrval));
}
};
struct and_expr : public expr {
expr *lhs, *rhs;
and_expr(expr* l, expr* r) : lhs(l), rhs(r) {}
bool accept(const user& u) override {
return lhs->accept(u) && rhs->accept(u);
}
};
struct or_expr : public expr {
expr *lhs, *rhs;
or_expr(expr* l, expr* r) : lhs(l), rhs(r) {}
bool accept(const user& u) override {
return lhs->accept(u) || rhs->accept(u);
}
};
int parse_int(const char*& pos) {
int ret = 0;
while (*pos >= '0' && *pos <= '9') ret = ret * 10 + (*pos - '0'), pos++;
return ret;
}
// base_expr := INT OP INT
expr* parse_base_expr(const char*& pos) {
int attrid = parse_int(pos);
int is_assert = (*pos == ':');
pos++; // skip : or ~
int attrval = parse_int(pos);
if (is_assert)
return new assert_expr(attrid, attrval);
else
return new nassert_expr(attrid, attrval);
}
// expr := base_expr | logic_expr
// logic_expr := LOGIC ( expr ) ( expr )
expr* parse_expr(const char*& pos) {
if (*pos >= '0' && *pos <= '9') return parse_base_expr(pos);
int is_and = (*pos == '&');
pos++; // skip | or &
pos++; // skip (
expr* lhs = parse_expr(pos);
pos++; // skip )
pos++; // skip (
expr* rhs = parse_expr(pos);
pos++; // skip )
if (is_and)
return new and_expr(lhs, rhs);
else
return new or_expr(lhs, rhs);
}
expr* parse(const char* pos) { return parse_expr(pos); }
int main() {
int users, queries;
cin >> users >> queries;
// read user info
vector<user> U(users);
for (auto& u : U) {
cin >> u.id;
int attrcnt, attrid, attrval;
cin >> attrcnt;
while (attrcnt--) {
cin >> attrid >> attrval;
u.attributes[attrid] = attrval;
}
}
// read and deal with queries
while (queries--) {
string exprtext;
cin >> exprtext;
expr* result = parse(exprtext.data());
vector<int> ans;
for (const auto& u : U)
if (result->accept(u)) ans.emplace_back(u.id);
sort(ans.begin(), ans.end());
copy(ans.begin(), ans.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}
return 0;
}