試題編號: | 201612-3 |
試題名稱: | 權限查詢 |
時間限制: | 1.0s |
內存限制: | 256.0MB |
問題描述: |
問題描述
授權 (authorization) 是各類業務系統不可缺少的組成部分,系統用戶通過授權機制獲得系統中各個模塊的操作權限。
本題中的授權機制是這樣設計的:每位用戶具有若干角色,每種角色具有若干權限。例如,用戶 david 具有 manager 角色,manager 角色有 crm:2 權限,則用戶 david 具有 crm:2 權限,也就是 crm 類權限的第 2 等級的權限。 具體地,用戶名和角色名稱都是由小寫字母組成的字符串,長度不超過 32。權限分為分等級權限和不分等級權限兩大類。分等級權限由權限類名和權限等級構成,中間用冒號“:”分隔。其中權限類名也是由小寫字母組成的字符串,長度不超過 32。權限等級是一位數字,從 0 到 9,數字越大表示權限等級越高。系統規定如果用戶具有某類某一等級的權限,那么他也將自動具有該類更低等級的權限。例如在上面的例子中,除 crm:2 外,用戶 david 也具有 crm:1 和 crm:0 權限。不分等級權限在描述權限時只有權限類名,沒有權限等級(也沒有用於分隔的冒號)。 給出系統中用戶、角色和權限的描述信息,你的程序需要回答多個關於用戶和權限的查詢。查詢可分為以下幾類: * 不分等級權限的查詢:如果權限本身是不分等級的,則查詢時不指定等級,返回是否具有該權限; * 分等級權限的帶等級查詢:如果權限本身分等級,查詢也帶等級,則返回是否具有該類的該等級權限; * 分等級權限的不帶等級查詢:如果權限本身分等級,查詢不帶等級,則返回具有該類權限的等級;如果不具有該類的任何等級權限,則返回“否”。
輸入格式
輸入第一行是一個正整數 p,表示不同的權限類別的數量。緊接着的 p 行被稱為 P 段,每行一個字符串,描述各個權限。對於分等級權限,格式為 <category>:<level>,其中 <category> 是權限類名,<level> 是該類權限的最高等級。對於不分等級權限,字符串只包含權限類名。
接下來一行是一個正整數 r,表示不同的角色數量。緊接着的 r 行被稱為 R 段,每行描述一種角色,格式為 <role> <s> <privilege 1> <privilege 2> ... <privilege s> 其中 <role> 是角色名稱,<s> 表示該角色具有多少種權限。后面 <s> 個字符串描述該角色具有的權限,格式同 P 段。 接下來一行是一個正整數 u,表示用戶數量。緊接着的 u 行被稱為 U 段,每行描述一個用戶,格式為 <user> <t> <role 1> <role 2> ... <role t> 其中 <user> 是用戶名,<t> 表示該用戶具有多少種角色。后面 <t> 個字符串描述該用戶具有的角色。 接下來一行是一個正整數 q,表示權限查詢的數量。緊接着的 q 行被稱為 Q 段,每行描述一個授權查詢,格式為 <user> <privilege>,表示查詢用戶 <user> 是否具有 <privilege> 權限。如果查詢的權限是分等級權限,則查詢中的 <privilege> 可指定等級,表示查詢該用戶是否具有該等級的權限;也可以不指定等級,表示查詢該用戶具有該權限的等級。對於不分等級權限,只能查詢該用戶是否具有該權限,查詢中不能指定等級。
輸出格式
輸出共 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 false
樣例說明
樣例輸入描述的場景中,各個用戶實際的權限如下:
* 用戶 alice 具有 crm:2 權限 * 用戶 bob 具有 crm:1、git:2 和 game 權限 * 用戶 charlie 具有 git:3 和 game 權限 * 用戶 malice 未描述,因此不具有任何權限
評測用例規模與約定
評測用例規模:
* 1 ≤ p, r, u ≤ 100 * 1 ≤ q ≤ 10 000 * 每個用戶具有的角色數不超過 10,每種角色具有的權限種類不超過 10 約定: * 輸入保證合法性,包括: 1) 角色對應的權限列表(R 段)中的權限都是之前(P 段)出現過的,權限可以重復出現,如果帶等級的權限重復出現,以等級最高的為准 2) 用戶對應的角色列表(U 段)中的角色都是之前(R 段)出現過的,如果多個角色都具有某一分等級權限,以等級最高的為准 3) 查詢(Q 段)中的用戶名和權限類名不保證在之前(U 段和 P 段)出現過 * 前 20% 的評測用例只有一種角色 * 前 50% 的評測用例權限都是不分等級的,查詢也都不帶等級
|
考試時毫無頭緒,輸入輸出都不知道如何處理,本文也是摘自他人,別人的思路真的是清晰明了。
#include<iostream> #include<string> using namespace std; struct Privilege //定義權限 { string name; int level; }; struct Role //定義角色 { string name; struct Privilege privilege[11]; int priviNum; }; struct User //定義用戶 { string name; struct Role uRole[11]; int roleNum; }; struct Privilege pri[101]; struct Role role[101]; struct User user[101]; int findPrivilege(string name) { for(int i=0;i<100;i++){ if(pri[i].name==name) return i; } return -1; } int findRole(string name) { for(int i=0;i<100;i++){ if(role[i].name==name) return i; } return -1; } int findUser(string name) { for(int i=0;i<100;i++){ if(name==user[i].name) return i; } return -1; } struct Privilege getPrivilege(string quanxian) { struct Privilege p;// 如果權限帶等級 if(quanxian.find(":",0)!=string::npos){ int pos=quanxian.find(":",0); p.name = quanxian.substr(0,pos); p.level = quanxian.at(quanxian.length()-1)-'0'; }//如果不帶等級 else{ p.name=quanxian; p.level=-1; } return p; } int main() { int p,u,r,q; string quanxian; scanf("%d",&p);//輸入權限 for(int i=0;i<p;i++){ cin>>quanxian; pri[i]=getPrivilege(quanxian); } cin>>r;//輸入角色 for(int i=0;i<r;i++){ string username; cin>>role[i].name; cin>>role[i].priviNum;//輸入角色的特權 for(int j=0;j<role[i].priviNum;j++){ string quanxian; cin>>quanxian; role[i].privilege[j]=getPrivilege(quanxian); } } cin>>u;//輸入用戶 for(int i=0;i<u;i++){ cin>>user[i].name; cin>>user[i].roleNum; for(int j=0;j<user[i].roleNum;j++){ string rolename; cin>>rolename; user[i].uRole[j]=role[findRole(rolename)]; } } cin>>q;//開始查詢 while(q--){ string name; string quanxian; cin>>name>>quanxian; int priviFlag=0,maxLevel=-1; if(findUser(name)!=-1){//找到用戶 User u=user[findUser(name)]; for(int j=0;j<u.roleNum;j++){//遍歷用戶的角色 for(int k=0;k<u.uRole[j].priviNum;k++){//遍歷每個角色的特權 struct Privilege p; p=getPrivilege(quanxian); if(p.name==u.uRole[j].privilege[k].name){//找到了帶權限的用戶 if(p.level==-1&&u.uRole[j].privilege[k].level==-1)//不分等級權限的不分等級查詢 priviFlag=1; else if(p.level==-1&&u.uRole[j].privilege[k].level!=-1){//分等級權限的不分等級查詢 if(maxLevel<u.uRole[j].privilege[k].level){ priviFlag=1; maxLevel=u.uRole[j].privilege[k].level; } } else if(p.level!=-1&&u.uRole[j].privilege[k].level!=-1){//分等級權限的分等級查詢 if(p.level<=u.uRole[j].privilege[k].level) priviFlag=1; } } } } } if(priviFlag==1&&maxLevel!=-1) cout<<maxLevel<<endl; else if(priviFlag==1&&maxLevel==-1) cout<<"true"<<endl; else if(priviFlag==0) cout<<"false"<<endl; } return 0; }