29届CSP第三题参考解答

简化的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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值