CCF-CSP 202206-3 角色授权

被卡时间卡了很久,最后还是过了。总结下来大概就是以下几点经验。

1.容器的选用方面,用set换vector,用unordered_map换map提高效率。

2.用map<string,role>存储角色信息相比直接开roles数组要高明,前者可以很快速地通过角色名找信息而不必逐个遍历。

3.仅针对这题来说,用户名和用户组名其实也没必要区分。

总的来说,找好合适的存储方式,这道题还是不难的。也正是因为似乎简单的遍历就能解决问题,在选择容器时才要仔细考虑,避免被卡时间。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

struct role {
	set<string>oprate;
	set<string>resourcekind;
	set<string>resource;
};
unordered_map<string, role>roles;
//前一项表示角色名,后一项表示该角色对应的操作,资源等
unordered_map<string, set<string>>assouserorgroup; 
//前一项表示用户或用户组名称,后一项表示角色名称

int main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);//加快输入输出
	int n, m, q;
	cin >> n >> m >> q;
	while (n--) {
		string name;
		int nv;
		cin >> name >> nv;
		while (nv--) {
			string op;cin >> op;
			roles[name].oprate.insert(op);
		}
		int no;cin >> no;
		while (no--) {
			string rk;cin >> rk;
			roles[name].resourcekind.insert(rk);
		}
		int nn;cin >> nn;
		while (nn--) {
			string res;cin >> res;
			roles[name].resource.insert(res);
		}
	}
	while (m--) {
		string rolename;cin >> rolename;
		int ns;cin >> ns;
		while (ns--) {
			string kind;
			string name;
			cin >> kind >> name; //后一项是用户组或用户名称
			assouserorgroup[name].insert(rolename);
		}
	}
	while (q--) {
		string username;
		set<string> userorgroupname;
		int ng;
		cin >> username >> ng;
		userorgroupname.insert(username);
		while (ng--) {
			string gname;
			cin >> gname, userorgroupname.insert(gname); 
//用户组名和用户名可以不做区分,似乎二者也不会重名
		}
		string opratename;cin >> opratename;
		string resourcekind;cin >> resourcekind;
		string resourcename;cin >> resourcename;
		set<string>ansrolename;
		int flag = 0;

		for (auto i : userorgroupname) {//对于每一个要查的用户名或用户组名
			if (assouserorgroup.count(i)) {//如果关联里有关联到这个用户名或用户组名,取出对应的角色名集合 assouserorgroup[i]
				for (auto j :assouserorgroup[i]) {//对于集合中每一个角色名,筛查对应的操作,资源种类和资源。一旦有一个符合要求就停止循环
					if ((roles[j].oprate.count(opratename)
					        || (roles[j].oprate.count("*")) )
					        && (roles[j].resourcekind.count(resourcekind)
					            || (roles[j].resourcekind.count("*")) )
					        && (roles[j].resource.count(resourcename) || roles[j].resource.size() == 0)) {
						flag = 1;
						break;
					}
				}
				if (flag == 1)
					break;
			}
		}
		cout << flag << "\n";
	}

	return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值