CCF CSP认证2022年6月 角色授权

太久没有写模拟题了,复健运动O(∩_∩)O哈哈~

T3

思路

考察stl的容器map,set应用。
通过两个map映射找到用户,或者用户所属用户组所关联的角色(准确来说是roles数组中下标),再对每个角色考虑授权。

map<string, vector<int>> usr2role;
map<string, vector<int>> group2role;

细节

对于多次询问,记得每一个询问开始时重新初始化gp.clear()

代码

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;

struct Role {
    
    
    string name;
    int nv, no, nn;
    set<string> op, kind, src;   // to optimize
    // 操作清单,资源种类清单,资源名称清单
    // 可能是通配符“*”
    bool f[3] = {
    
    0, 0, 0};  // 通配符标志位
} roles[505];
map<string, int> name2i;

// 从用户(组)出发查找关联的所有角色(的数组下标)
map<string, vector<int>> usr2role;
map<string, vector<int>> group2role;

void solve() {
    
    
    int n, m, q;
    cin >> n >> m >> q;

    // 构建角色
    string str; int d;
    for (int i = 0; i < n; i++) {
    
    
        Role r;
        cin >> str; r.name = str;
        cin >> d; r.nv = d;
        for (int j = 0; j < d; j++) {
    
    
            cin >> str; r.op.emplace(str);
            if (str == "*") r.f[0] = 1;
        }
        cin >> d; r.no = d;
        for (int j = 0; j < d; j++) {
    
    
            cin >> str; r.kind.emplace(str);
            if (str == "*") r.f[1] = 1;
        }
        cin >> d; r.nn = d;
        for (int j = 0; j < d; j++) {
    
    
            cin >> str; r.src.emplace(str);
        }
        roles[i] = r;
        name2i[r.name] = i; // 根据角色名称查找角色信息
    }

    // 构建角色关联
    string u, rr, t;    // 用户(组),角色,类型
    for (int i = 0; i < m; i++) {
    
    
        cin >> rr; cin >> d;
        for (int j = 0; j < d; j++) {
    
    
            cin >> t >> u;
            if (t == "u") {
    
     usr2role[u].push_back(name2i[rr]); }
            if (t == "g") {
    
     group2role[u].push_back(name2i[rr]); }
        }
    }

    vector<string> gp;  // 所属用户组列表,必须存储
    string o, k, s;     // 该操作的名称,资源种类,资源名称
    while (q--) {
    
    
        cin >> u;
        cin >> d;
        for (int j = 0; j < d; j++) {
    
    
            cin >> str; gp.push_back(str);
        }
        cin >> o >> k >> s;
        bool ok = 0;
        // 从用户名称出发查找
        for (int i : usr2role[u]) {
    
    
            bool x, y, z;   // 标志位初始化为0
            x = y = z = 0;
            if (roles[i].f[0]) {
    
     x = 1; }
            else if (roles[i].op.find(o) != roles[i].op.end()) {
    
     x = 1; }
            if (roles[i].f[1]) {
    
     y = 1; }
            else if (roles[i].kind.find(k) != roles[i].kind.end()) {
    
     y = 1; }

            if (roles[i].src.empty()) {
    
     z = 1; }
            else
            if (roles[i].src.find(s) != roles[i].src.end()) {
    
     z = 1; }

            if (x && y && z) {
    
     ok = 1; break; }
        }
        // 从所在用户组名称出发查找
        if (!ok)
        for (string i : gp) {
    
    
            for (int j : group2role[i]) {
    
      // 所关联角色
                bool x, y, z;
                x = y = z = 0;

                if (roles[j].f[0]) {
    
     x = 1; }
                else if (roles[j].op.find(o) != roles[j].op.end()) {
    
     x = 1; }
                if (roles[j].f[1]) {
    
     y = 1; }
                else if (roles[j].kind.find(k) != roles[j].kind.end()) {
    
     y = 1; }

                if (roles[j].src.empty()) {
    
     z = 1; }
                else
                if (roles[j].src.find(s) != roles[j].src.end()) {
    
     z = 1; }

                if (x && y && z) {
    
     ok = 1; break; }
            }
            if (ok) break;
        }
        if (ok) cout << "1\n";
        else cout << "0\n";
        gp.clear();
    }
}

int main() {
    
    
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_23096319/article/details/129349936