acwing满分,从集合的角度看待问题
定义一系列集合,集合的元素都是角色:
1、为每个操作名、资源名、资源种类定义一个集合,表示哪些角色有资格操作;
2、为了应对如*这样可以操作任何类别的角色,再定义三个集合:任意操作集合、任意资源名集合、任意资源种类集合;
3、为每个用户名、用户组名定义一个集合,表示哪些角色与之有关联;
那么为了判断某用户是否能完成某行为,只需要将其用户名集合和涉及的所有用户组名集合求并集(bitset的按位或),得到所有与之相关联的角色;再依次与该行为对应的操作名、资源名、资源种类集合求交集(bitset的按位与),当然不要忘了处理任意操作集合、任意资源名集合、任意资源种类集合。这样就可以得到既与该角色关联,又被允许操作的角色集合,这个集合不为空的话,就代表可以完成该行为。详情见代码。
C++ 代码
#include<bits/stdc++.h>
using namespace std;
int n, m, q;
int nv, no, nn, ns, ng;
string tmpStr;
string userName, opName, sourceType, sourceName, userGroupName;
unordered_map<string, int> actors;
int actorIndex = 0;
unordered_map<string, bitset<507>> op_set;
unordered_map<string, bitset<507>> source_type_set;
unordered_map<string, bitset<507>> source_name_set;
bitset<507> any_op_set;
bitset<507> any_source_type_set;
bitset<507> any_source_name_set;
unordered_map<string, bitset<507>> user_set;
unordered_map<string, bitset<507>> user_group_set;
int main(){
// ios::sync_with_stdio(false);
// cin.tie(0), cout.tie(0);
cin >> n >> m >> q;
for(int i = 1; i <= n; ++i){// 输入角色
cin >> tmpStr;
actors[tmpStr] = actorIndex;
cin >> nv;
while(nv--){
cin >> tmpStr;
if(tmpStr == "*"){
any_op_set[actorIndex] = 1;
}else{
op_set[tmpStr][actorIndex] = 1;
}
}
cin >> no;
while(no--){
cin >> tmpStr;
if(tmpStr == "*"){
any_source_type_set[actorIndex] = 1;
}else{
source_type_set[tmpStr][actorIndex] = 1;
}
}
cin >> nn;
if(nn == 0){
any_source_name_set[actorIndex] = 1;
}
while(nn--){
cin >> tmpStr;
source_name_set[tmpStr][actorIndex] = 1;
}
++actorIndex;
}
for(int i = 1; i <= m; ++i){
cin >> tmpStr;
cin >> ns;
string type;
while(ns--){
cin >> type;
if(type=="u"){
cin >> userName;
user_set[userName][actors[tmpStr]] = 1;
}else{
cin >> userGroupName;
user_group_set[userGroupName][actors[tmpStr]] = 1;
}
}
}
for(int i = 1; i <= q; ++i){
cin >> userName;
bitset<507> res;
res |= user_set[userName];
cin >> ng;
while(ng--){
cin >> userGroupName;
res |= user_group_set[userGroupName];
}
cin >> opName;
res &= op_set[opName] | any_op_set;
cin >> sourceType;
res &= source_type_set[sourceType] | any_source_type_set;
cin >> sourceName;
res &= source_name_set[sourceName] | any_source_name_set;
cout << res.any() ? 1 : 0;
cout << '\n';
}
return 0;
}