详细注释都在代码里了
代码中相关的知识:
#include <iostream>
#include <string>
#include <algorithm>
#include <set>
#include <unordered_map>
//本道题三种关系依次嵌套,在想好如何存储之后便可以开始写了
//省略了person中role的存储,在读入中将role转化为对应的权限,所以person里存的也是权限
using namespace std;
struct P
{
string pname;
mutable int level;//因为要修改set中的值,所以要把level前面加上mutable
P(string str)//结构体的初始化
{
int pos = str.find(':'); //如果没有冒号说明没有等级权限
if (pos == -1)pname = str, level = -1;//-1表示无等级权限
else
{
pname = str.substr(0, pos);//将str中从第0个字符开始,长度是五的字符串copy给name,详细用法见下图
level = stoi(str.substr(pos + 1,1));//stoi将string转化为int
}
}
bool operator<(const P& W)const//因为用了set存储结构体,所以需要运算符重载
{
return pname < W.pname;
}
};
unordered_map<string, set<P>> person, role;
int main()
{
int n;
string name, right;
cin >> n;
while (n--)cin >> name;
cin >> n;//role的读入
while (n--)
{
cin >> name;
int cnt;
cin >> cnt;
set<P>& r = role[name];
while (cnt--)
{
cin >> right;
P tmp(right);//让right符合规范
if (tmp.level == -1)r.insert(tmp);//无等级权限
else
{
if (!r.count(tmp))r.insert(tmp);//之前没有这个权限
else
{
auto t = r.find(tmp);//找到已经存储的权限
t->level = max(t->level, tmp.level);//取最高等级的权限
}
}
}
}
cin >> n;//person的读入
while (n--)
{
cin >> name;
int cnt;
cin >> cnt;
set<P>& p = person[name];
while (cnt--)
{
string str;
cin >> str;//角色role
for (auto& tmp : role[str])//枚举角色 role[str]是一个权限集合set<P>
{
if (tmp.level == -1)p.insert(tmp);//无等级权限
else
{
if (!p.count(tmp))p.insert(tmp);//之前没有这个权限
else
{
auto t = p.find(tmp);//找到已经存储的权限
t->level = max(t->level, tmp.level);//取最高等级的权限
}
}
}
}
}
cin >> n; //读入所有的询问
while (n--)
{
string username, pr; //读入用户名和权限
cin >> username >> pr;
P t(pr); //将权限变成结构体
set<P>& p = person[username];
if (!p.count(t)) puts("false");
else
{
auto it = p.find(t);
if (t.level != -1)
{
if (it->level >= t.level) puts("true");
else puts("false");
}
else
{
if (it->level == -1) puts("true"); //不分等级权限,有该权限
else cout << it->level << endl; //分等级权限,但是不指定查询等级,输出该用户拥有的最高等级权限
}
}
}
return 0;
}