赞
踩
最后要求输出符合条件的用户 DN 的集合, (作为一名STL战士) ,可以考虑维护以属性名和属性值为索引, 对应值为符合条件的用户的set 的一个map
属性名 -> 属性值 -> {用户1,用户2…}
unordered_map<int,unordered_map<int,set<int>>> attrName_attrVal_users;
操作分为原子操作和逻辑操作, 只需要判断字符串的首字符即可区分两种操作
原子操作分为匹配和剔除, 匹配满足条件(属性名为相应属性值)的用户集合可以直接从刚才的map里找到, 作为答案, 而剔除时需要注意, 只有当用户该属性有值且不为指定值时才能作为答案, 所以为了便于判断用户指定属性是否有值(不为N/A), 可以维护一个以属性名为索引, 值为相应用户集合的map
属性名 -> {用户1,用户2…}
unordered_map<int, set<int>> attrName_users;
逻辑操作主要是符合条件的用户集合的交和并, 以及逻辑操作的嵌套, 这里用两个set ans1
和ans2
来暂存符合条件的用户
ans.insert(ans1.begin(), ans1.end());
ans.insert(ans2.begin(), ans2.end());
for(auto it : ans1) {
if(ans2.count(it)) {
ans.insert(it);
}
}
对于一个逻辑操作表达式的前后两个部分, 我们发现他们无论怎么嵌套, 每个部分的括号一定是匹配的, 可以维护一个括号栈, 遍历字符串直到括号栈空, 此时字符串的位置 (本文为p
) 为前后两个部分的分界位置
然后递归调用即可
#include<bits/stdc++.h> using namespace std; int n; unordered_map<int,unordered_map<int,set<int>>> attrName_attrVal_users; // 存储 属性名-属性值-用户DN unordered_map<int, set<int>> attrName_users; // 存储该属性不为NA的用户DN set int getNum(string exp) {// 字符串转整形 int ans = 0; for(int i = 0; i < exp.size(); i++) { ans *= 10; ans += (exp[i] - '0'); } return ans; } set<int> AtomOP(string exp) {// 原子操作 int p = 0;set<int> ans; while(exp[p] != ':' && exp[p] != '~') p++; int a = getNum(exp.substr(0,p)); int b = getNum(exp.substr(p+1, exp.size())); if(exp[p] == ':') { ans.insert(attrName_attrVal_users[a][b].begin(), attrName_attrVal_users[a][b].end()); } else { ans.insert(attrName_users[a].begin(), attrName_users[a].end()); set<int> dead; for(auto it : attrName_attrVal_users[a][b]) { if(ans.count(it)) { dead.insert(it); } } for(auto it : dead) ans.erase(it); } return ans; } set<int> ExprOP(string exp) { set<int> ans; if(exp[0] >= '0' && exp[0] <= '9') { ans = AtomOP(exp); } else if(exp[0] == '&') { int p = 1;set<int> ans1;set<int> ans2; stack<char> br;br.push('('); while(!br.empty()) { p++; if(exp[p] == '(') { br.push('('); } else if(exp[p] == ')') { br.pop(); } } ans1 = ExprOP(exp.substr(2, p-2)); int q = p+2;br.push('('); while(!br.empty()) { q++; if(exp[q] == '(') { br.push('('); } else if(exp[q] == ')') { br.pop(); } } ans2 = ExprOP(exp.substr(p+2, q-p-2)); for(auto it : ans1) { if(ans2.count(it)) { ans.insert(it); } } } else if(exp[0] == '|') { int p = 1;set<int> ans1;set<int> ans2; stack<char> br;br.push('('); while(!br.empty()) { p++; if(exp[p] == '(') { br.push('('); } else if(exp[p] == ')') { br.pop(); } } ans1 = ExprOP(exp.substr(2, p-2)); int q = p+2;br.push('('); while(!br.empty()) { q++; if(exp[q] == '(') { br.push('('); } else if(exp[q] == ')') { br.pop(); } } ans2 = ExprOP(exp.substr(p+2, q-p-2)); ans.insert(ans1.begin(), ans1.end()); ans.insert(ans2.begin(), ans2.end()); } return ans; } int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin >> n; for(int i = 1; i <= n; i++) { int dn;cin >> dn; int num;cin >> num; users.insert(dn); for(int j = 1; j <= num; j++) { int attrName;cin >> attrName; int attrVal; cin >> attrVal; attrName_attrVal_users[attrName][attrVal].insert(dn); attrName_users[attrName].insert(dn); } } int m; cin >> m; for(int i = 1; i <= m; i++) { string exp;cin >> exp; set<int> ans; ans = ExprOP(exp); for(auto it : ans) { cout << it << " "; } cout << endl; } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。