問題描述
授權 (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 段,每行一個字符串,描述各個權限。對於分等級權限,格式爲 :,其中 是權限類名, 是該類權限的最高等級。對於不分等級權限,字符串只包含權限類名。
接下來一行是一個正整數 r,表示不同的角色數量。緊接着的 r 行被稱爲 R 段,每行描述一種角色,格式爲
<privilege 1> <privilege 2> …
其中 是角色名稱, 表示該角色具有多少種權限。後面 個字符串描述該角色具有的權限,格式同 P 段。
接下來一行是一個正整數 u,表示用戶數量。緊接着的 u 行被稱爲 U 段,每行描述一個用戶,格式爲
<role 1> <role 2> …
其中 是用戶名, 表示該用戶具有多少種角色。後面 個字符串描述該用戶具有的角色。
接下來一行是一個正整數 q,表示權限查詢的數量。緊接着的 q 行被稱爲 Q 段,每行描述一個授權查詢,格式爲 ,表示查詢用戶 是否具有 權限。如果查詢的權限是分等級權限,則查詢中的 可指定等級,表示查詢該用戶是否具有該等級的權限;也可以不指定等級,表示查詢該用戶具有該權限的等級。對於不分等級權限,只能查詢該用戶是否具有該權限,查詢中不能指定等級。輸出格式 輸出共 q 行,每行爲 false、true,或者一個數字。false 表示相應的用戶不具有相應的權限,true 表示相應的用戶具有相應的權限。對於分等級權限的不帶等級查詢,如果具有權限,則結果是一個數字,表示該用戶具有該權限的(最高)等級。如果用戶不存在,或者查詢的權限沒有定義,則應該返回 false。
評測用例規模:
* 1 ≤ p, r, u ≤ 100
* 1 ≤ q ≤ 10 000
* 每個用戶具有的角色數不超過 10,每種角色具有的權限種類不超過 10
約定:
* 輸入保證合法性,包括:
1) 角色對應的權限列表(R 段)中的權限都是之前(P 段)出現過的,權限可以重複出現,如果帶等級的權限重複出現,以等級最高的爲準
2) 用戶對應的角色列表(U 段)中的角色都是之前(R 段)出現過的,如果多個角色都具有某一分等級權限,以等級最高的爲準
3) 查詢(Q 段)中的用戶名和權限類名不保證在之前(U 段和 P 段)出現過
前 20% 的評測用例只有一種角色
* 前 50% 的評測用例權限都是不分等級的,查詢也都不帶等級
解題思路:
CCF前幾年的第三題雖然題目複雜,但是沒有用到算法,需要耐心仔細,讀懂題目。
本題我用三個map來表示題目中的三個不同類型數據,爲的是查詢方便,題目中有好多值得注意的地方,我已經加粗,其中用例就是根據最後一個加粗條目構造,從而得到結果。還有就是本題數據結構的構建要清晰,沒有其他需要注意的點。
找到錯誤的測試用例:
3
crm:2
git:3
game
1
it 3 crm:1 git:1 game
3
alice 1 it
bob 2 it qa
charlie 1 dev
6
alice game
alice ccc
bob crm:0
bob crm
bob game
charlie game
#include<iostream>
#include<string>
#include<cstring>
#include<map>
using namespace std;
typedef struct nod{
string qname[101];
int gra[101];
}Qx;
typedef struct node{
string jname[102];
}Node;
map<string,Node> user; //用戶
map<string,Qx> actor;//角色
//map的value中不能用結構體數組,而是結構體中的數組
map<string,int > pow;//權限
void fenli (string s1,string &s2,int &n){
int pos=s1.find(":");
if(pos==-1){//沒:
n=-1;
s2=s1;
}
else{//有:
s2=s1;
s2.erase(pos,s2.size()-pos);
n=s1[pos+1]-'0';
}
}
int main(){
int p;
cin>>p;//權限
string ss;
string tmp;
int n=0;
for(int i=0;i<p;i++){
n=-1;
cin>>tmp;
fenli(tmp,ss,n);
pow[ss]=n;
}//cout<<"****git"<<pow["crm"]<<endl;
int r;
cin>>r;//角色
for(int i=0;i<r;i++){
string name;
struct nod qtmp;
cin>>name;
int s;
cin>>s;
for(int j=0;j<s;j++){
cin>>tmp;
n=-1;
fenli(tmp,ss,n);
actor[name].qname[j]=ss;
actor[name].gra[j]=n;
}
}
int u;
cin>>u;//user
for(int i=0;i<u;i++){
string a,b;
int x;
cin>>a;
cin>>x;
for(int j=0;j<x;j++){
cin>>b;
user[a].jname[j]=b;
}
}
int q;
cin>>q;//查詢
for(int k=0;k<q;k++){
string a,b;
cin>>a>>b;
n=0;
fenli(b,ss,n);//cout<<"************"<<n<<endl;
int i=0;
string ttmp;
bool flag=false;
int ts=-1;
while((ttmp=user[a].jname[i])!=""){
int j=0;
while(actor[ttmp].qname[j]!=""){
if(ss==actor[ttmp].qname[j]&&n<=actor[ttmp].gra[j]){
flag=true;
if(n==-1){
if(ts<actor[ttmp].gra[j]){
ts=actor[ttmp].gra[j];
//cout<<"***"<<ttmp<<" "<<actor[ttmp].qname[1]<<" "<<actor[ttmp].gra[1]<<endl;
}
}
}
j++;
}
i++;
}
if(flag==true&&ts==-1) cout<<"true"<<endl;
else if(flag&&ts>=0) cout<<ts<<endl;
else cout<<"false"<<endl;
}
}