CSP 權限查詢

問題描述

  • 受權 (authorization) 是各種業務系統不可缺乏的組成部分,系統用戶經過受權機制得到系統中各個模塊的操做權限。
  • 本題中的受權機制是這樣設計的:每位用戶具備若干角色,每種角色具備若干權限。例如,用戶 david 具備 manager 角色,manager 角色有 crm:2 權限,則用戶 david 具備 crm:2 權限,也就是 crm 類權限的第 2 等級的權限。
  • 具體地,用戶名和角色名稱都是由小寫字母組成的字符串,長度不超過 32。權限分爲分等級權限和不分等級權限兩大類。分等級權限由權限類名和權限等級構成,中間用冒號「:」分隔。其中權限類名也是由小寫字母組成的字符串,長度不超過 32。權限等級是一位數字,從 0 到 9,數字越大表示權限等級越高。系統規定若是用戶具備某類某一等級的權限,那麼他也將自動具備該類更低等級的權限。例如在上面的例子中,除 crm:2 外,用戶 david 也具備 crm:1 和 crm:0 權限。不分等級權限在描述權限時只有權限類名,沒有權限等級(也沒有用於分隔的冒號)。
  • 給出系統中用戶、角色和權限的描述信息,你的程序須要回答多個關於用戶和權限的查詢。查詢可分爲如下幾類:
    • 不分等級權限的查詢:若是權限自己是不分等級的,則查詢時不指定等級,返回是否具備該權限;
    • 分等級權限的帶等級查詢:若是權限自己分等級,查詢也帶等級,則返回是否具備該類的該等級權限;
    • 分等級權限的不帶等級查詢:若是權限自己分等級,查詢不帶等級,則返回具備該類權限的等級;若是不具備該類的任何等級權限,則返回「否」。c++

      輸入格式

  • 輸入第一行是一個正整數 p,表示不一樣的權限類別的數量。緊接着的 p 行被稱爲 P 段,每行一個字符串,描述各個權限。對於分等級權限,格式爲 : ,其中 是權限類名, 是該類權限的最高等級。對於不分等級權限,字符串只包含權限類名。
  • 接下來一行是一個正整數 r,表示不一樣的角色數量。緊接着的 r 行被稱爲 R 段,每行描述一種角色,格式爲
    • <s> <privilege 1> <privilege 2> ...
    • 其中 是角色名稱,<s> 表示該角色具備多少種權限。後面 <s> 個字符串描述該角色具備的權限,格式同 P 段。
  • 接下來一行是一個正整數 u,表示用戶數量。緊接着的 u 行被稱爲 U 段,每行描述一個用戶,格式爲
    • <role 1> <role 2> ...
    • 其中 是用戶名, 表示該用戶具備多少種角色。後面 個字符串描述該用戶具備的角色。
  • 接下來一行是一個正整數 q,表示權限查詢的數量。緊接着的 q 行被稱爲 Q 段,每行描述一個受權查詢,格式爲
    • ,表示查詢用戶 是否具備 權限。
    • 若是查詢的權限是分等級權限,則查詢中的 可指定等級,表示查詢該用戶是否具備該等級的權限;
    • 也能夠不指定等級,表示查詢該用戶具備該權限的等級。
    • 對於不分等級權限,只能查詢該用戶是否具備該權限,查詢中不能指定等級。git

      輸出格式

  • 輸出共 q 行,每行爲 false、true,或者一個數字。
  • false 表示相應的用戶不具備相應的權限,
  • true 表示相應的用戶具備相應的權限。
  • 對於分等級權限的不帶等級查詢,若是具備權限,則結果是一個數字,表示該用戶具備該權限的(最高)等級。
  • 若是用戶不存在,或者查詢的權限沒有定義,則應該返回 false。數據結構

    樣例輸入

    3
    crm:2
    git:3
    game
    4
    hr 1 crm:2
    it 3 crm:1 git:1 game
    dev 2 git:3 game
    qa 1 git:2
    3
    alice 1 hr
    bob 2 it qa
    charlie 1 dev
    9
    alice game
    alice crm:2
    alice git:0
    bob git
    bob poweroff
    charlie game
    charlie crm
    charlie git:3
    malice game測試

    樣例輸出

    false
    true
    false
    2
    false
    true
    false
    true
    falsespa

    樣例說明

  • 樣例輸入描述的場景中,各個用戶實際的權限以下:
    • 用戶 alice 具備 crm:2 權限
    • 用戶 bob 具備 crm:一、git:2 和 game 權限
    • 用戶 charlie 具備 git:3 和 game 權限
    • 用戶 malice 未描述,所以不具備任何權限設計

      評測用例規模與約定

  • 評測用例規模:
    • 1 ≤ p, r, u ≤ 100
    • 1 ≤ q ≤ 10000
    • 每一個用戶具備的角色數不超過 10,每種角色具備的權限種類不超過 10
  • 約定:
    • 輸入保證合法性,包括:
        1) 角色對應的權限列表(R 段)中的權限都是以前(P 段)出現過的,權限能夠重複出現,若是帶等級的權限重複出現,以等級最高的爲準
        2) 用戶對應的角色列表(U 段)中的角色都是以前(R 段)出現過的,若是多個角色都具備某一分等級權限,以等級最高的爲準
        3) 查詢(Q 段)中的用戶名和權限類名不保證在以前(U 段和 P 段)出現過
        * 前 20% 的評測用例只有一種角色
        * 前 50% 的評測用例權限都是不分等級的,查詢也都不帶等級

分析

  • 這個問題嵌套嚴重,角色擁有多個權限,用戶擁有多個角色,權限有分等級和不分等級
  • 輸入時,將每一個用戶對應到權限,有等級權限存儲最大的
  • 設計合適的數據結構是求解這題的關鍵
  • 對於輸出的判斷
  • 個人代碼寫的比較粗糙,沒有重構
#include <bits/stdc++.h>
using namespace std;
int p,r,u,q;
class Role;
class User;
map<string,int>hasLevRight;
map<string,int>noLevRight;
map<string,Role>roles;
map<string,User>users;
typedef pair<string,int>P;

class Role
{
public:
    string roleName;
    map<string,int>levedRight;
    map<string,int>unlevedRight;
};

class User
{
public:
    string userName;
    map<string,int>levedRight;
    map<string,int>unlevedRight;
};

int stringToInt(string s)
{
    int num=0;
    for(int i=0;i<s.size();i++)
        num = num*10+s[i]-'0';
    return num;
}

P processRIght(string s)
{
    string first,second;
    int i=0;
    for(;i<s.size()&&s[i]!=':';i++)
        first+=s[i];
    for(i++;i<s.size();i++)
        second+=s[i];
    if(second != "") return P(first,stringToInt(second));
    else return P(first,-1);
}

// 未測試
void combine(string name,string roleName,User& user)
{
    //cout<<name<<"  "<<roleName<<endl;
    Role role = roles[roleName];
    //cout<<role.roleName<<"  ";
    map<string,int>::iterator iter;
    for(iter = role.levedRight.begin();iter!=role.levedRight.end();iter++)
    {
        string rightName = iter->first;
        int lev = iter->second;
        user.levedRight[rightName] = max(lev,user.levedRight[rightName]);
    }
    for(iter = role.unlevedRight.begin();iter!=role.unlevedRight.end();iter++)
    {
        string rightName = iter->first;
        user.unlevedRight[rightName]=-1;
    }
}


void input1()
{
    string s,first,second;
    cin>>p;
    getchar();
    while(p--){
        getline(cin,s );
        P all = processRIght(s);
        string first = all.first;
        int lev = all.second;
        if(lev==-1) noLevRight[first]=-1;
        else hasLevRight[first]=lev;
    }
}

void input2()
{
    string s,name;
    int num;
    cin>>r;
    while(r--)
    {
        Role role;
        cin>>name>>num;
        role.roleName = name;
        while(num--)
        {
            cin>>s;
            P all = processRIght(s);
            string first = all.first;
            int lev = all.second;
            if(lev==-1) role.unlevedRight[first]=-1;
            else role.levedRight[first] = max(lev,role.levedRight[first]);
            roles[name] = role;
        }

    }
}

void input3()
{
    string s,name;
    int num;
    cin>>u;
    while(u--)
    {
        cin>>name>>num;
        User user;
        user.userName = name;
        while(num--)
        {
            cin>>s;
            combine(name,s,user);
        }
        users[name]=user;
    }
}

void input4()
{
    string userName,s;
    cin>>q;
    while(q--)
    {
        cin>>userName>>s;
        if(!users.count(userName)){     //用戶不存在
            cout<<"false"<<endl;
            continue;
        }
        User user = users[userName];

        P all = processRIght(s);
        string first = all.first;
        int lev = all.second;
        // 權限不存在
        if(!hasLevRight.count(first)&&!noLevRight.count(first)){
            cout<<"false"<<endl;
            continue;
        }

        if(noLevRight.count(first)) // un Leved
        {
            if(user.unlevedRight.count(first)) cout<<"true"<<endl;
            else cout<<"false"<<endl;
        }
        else if(hasLevRight.count(first)){  //leved Right
            if(!user.levedRight.count(first)){
                cout<<"false"<<endl;
            }
            else {
                if(lev==-1) cout<<user.levedRight[first]<<endl;
                else {
                    if(user.levedRight[first]>=lev) cout<<"true"<<endl;
                    else cout<<"false"<<endl;
                }
            }

        }
    }
}

// 輸出全部內存中的數據,測試
void output()
{
    // 全部的權限
    map<string,int>::iterator iter;
    for(iter = hasLevRight.begin();iter!=hasLevRight.end();iter++)
    {
        cout<<iter->first<<"  "<<iter->second<<endl;
    }
    for(iter = noLevRight.begin();iter!=noLevRight.end();iter++)
        cout<<iter->first<<"  "<<iter->second<<endl;
    cout<<"----------------------------------"<<endl;

    // 每一個角色的權限
    map<string,Role>::iterator iter2;
    for(iter2 = roles.begin();iter2!=roles.end();iter2++)
    {
        Role role = iter2->second;
        cout<<role.roleName<<":"<<endl;
        for(iter = role.levedRight.begin();iter!=role.levedRight.end();iter++)
            cout<<iter->first<<"  "<<iter->second<<"  ";
        cout<<endl;
        for(iter = role.unlevedRight.begin();iter!=role.unlevedRight.end();iter++)
            cout<<iter->first<<"  ";
        cout<<endl;

    }
    cout<<"-------------------------------------"<<endl;
    // 每一個用戶的權限
    map<string,User>::iterator iter3;
    for(iter3 = users.begin();iter3!=users.end();iter3++)
    {
        User user = iter3->second;
        cout<<user.userName<<"  :"<<endl;
        for(iter = user.levedRight.begin();iter!=user.levedRight.end();iter++)
            cout<<iter->first<<"  "<<iter->second<<"  ";
        cout<<endl;
        for(iter = user.unlevedRight.begin();iter!=user.unlevedRight.end();iter++)
            cout<<iter->first<<"  ";
        cout<<endl;
    }
}

int main()
{
    //freopen("I:\\new 1.txt","r",stdin);
    input1();
    input2();
    input3();
    input4();
    //output();
    return 0;
}
相關文章
相關標籤/搜索