【CCF】權限查詢
阿新 • • 發佈:2018-03-11
個數 hda ron style algo 接下來 系統用戶 ans space 問題描述
授權 (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% 的評測用例權限都是不分等級的,查詢也都不帶等級 分析 題目很簡單,思路很清晰,就是代碼量有點大,寫著寫著容易混亂。
本題中的授權機制是這樣設計的:每位用戶具有若幹角色,每種角色具有若幹權限。例如,用戶 david 具有 manager 角色,manager 角色有 crm:2 權限,則用戶 david 具有 crm:2 權限,也就是 crm 類權限的第 2 等級的權限。
具體地,用戶名和角色名稱都是由小寫字母組成的字符串,長度不超過 32。權限分為分等級權限和不分等級權限兩大類。分等級權限由權限類名和權限等級構成,中間用冒號“:”分隔。其中權限類名也是由小寫字母組成的字符串,長度不超過 32。權限等級是一位數字,從 0 到 9,數字越大表示權限等級越高。系統規定如果用戶具有某類某一等級的權限,那麽他也將自動具有該類更低等級的權限。例如在上面的例子中,除 crm:2 外,用戶 david 也具有 crm:1 和 crm:0 權限。不分等級權限在描述權限時只有權限類名,沒有權限等級(也沒有用於分隔的冒號)。
給出系統中用戶、角色和權限的描述信息,你的程序需要回答多個關於用戶和權限的查詢。查詢可分為以下幾類:
* 不分等級權限的查詢:如果權限本身是不分等級的,則查詢時不指定等級,返回是否具有該權限;
* 分等級權限的帶等級查詢:如果權限本身分等級,查詢也帶等級,則返回是否具有該類的該等級權限;
* 分等級權限的不帶等級查詢:如果權限本身分等級,查詢不帶等級,則返回具有該類權限的等級;如果不具有該類的任何等級權限,則返回“否”。 輸入格式 輸入第一行是一個正整數 p
接下來一行是一個正整數 r,表示不同的角色數量。緊接著的 r 行被稱為 R 段,每行描述一種角色,格式為
<role> <s> <privilege 1> <privilege 2> ... <privilege s>
其中 <role> 是角色名稱,<s> 表示該角色具有多少種權限。後面 <s> 個字符串描述該角色具有的權限,格式同 P 段。
接下來一行是一個正整數 u
<user> <t> <role 1> <role 2> ... <role t>
其中 <user> 是用戶名,<t> 表示該用戶具有多少種角色。後面 <t> 個字符串描述該用戶具有的角色。
接下來一行是一個正整數 q,表示權限查詢的數量。緊接著的 q 行被稱為 Q 段,每行描述一個授權查詢,格式為 <user> <privilege>,表示查詢用戶 <user> 是否具有 <privilege> 權限。如果查詢的權限是分等級權限,則查詢中的 <privilege> 可指定等級,表示查詢該用戶是否具有該等級的權限;也可以不指定等級,表示查詢該用戶具有該權限的等級。對於不分等級權限,只能查詢該用戶是否具有該權限,查詢中不能指定等級。 輸出格式 輸出共 q
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% 的評測用例權限都是不分等級的,查詢也都不帶等級 分析 題目很簡單,思路很清晰,就是代碼量有點大,寫著寫著容易混亂。
1 #include <iostream> 2 #include <iomanip> 3 #include <cstdio> 4 #include <string.h> 5 #include <cstring> 6 #include <algorithm> 7 #include <cmath> 8 #include <string> 9 #include <queue> 10 #include <map> 11 #include <vector> 12 #include <set> 13 #include <list> 14 using namespace std; 15 typedef long long ll; 16 const int INF = 0x3f3f3f3f; 17 const int NINF = 0xc0c0c0c0; 18 const int maxn = 105; 19 int MonthDay[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 20 string MonthName[] = {"Jan","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; 21 string DayName[] = {"Sun", "Mon","Tue","Wed","Thu","Fri","Sat"}; 22 struct Category 23 { 24 string category_name; 25 bool have_level; 26 int level; 27 Category(){} 28 Category(string n, bool h, int l):category_name(n), have_level(h),level(l){} 29 }; 30 struct Role 31 { 32 string role_name; 33 Category category[maxn]; 34 int cname_num; 35 Role(){} 36 37 }; 38 struct User 39 { 40 string user_name; 41 string rname[maxn]; 42 int rname_num; 43 User(){} 44 45 }; 46 Category ca[maxn]; 47 Role ro[maxn]; 48 User us[maxn]; 49 int stringToInt(string s) 50 { 51 int ans = 0; 52 for(int i = 0; i < s.size(); i++) { 53 ans = ans*10+s[i]-‘0‘; 54 } 55 return ans; 56 } 57 int main() { 58 freopen("/Users/kangyutong/Desktop/in.txt","r",stdin); 59 // freopen("/Users/kangyutong/Desktop/out.txt","w", stdout); 60 61 int p, r, u, q; 62 cin >> p; 63 string str; 64 for(int i = 0; i < p; i++) { 65 cin >> str; 66 int pos = (int)str.find(‘:‘); 67 if(pos != -1) { 68 ca[i].have_level = true; 69 ca[i].category_name = str.substr(0,pos); 70 string temp = str.substr(pos+1, str.size()-1-pos); 71 ca[i].level = stringToInt(temp); 72 // cout << ca[i].category_name << endl; 73 // cout << ca[i].level << endl; 74 } 75 else { 76 ca[i].category_name = str; 77 ca[i].have_level = false; 78 } 79 80 } 81 cin >> r; 82 string str1, str2; 83 int m; 84 for(int i = 0; i < r; i++) { 85 cin >> str1 >> m; 86 ro[i].role_name = str1; 87 ro[i].cname_num = m; 88 for(int j = 0; j < m; j++) { 89 cin >> str2; 90 int pos = (int)str2.find(‘:‘); 91 if(pos != -1) { 92 ro[i].category[j].category_name = str2.substr(0, pos); 93 string temp = str2.substr(pos+1, str2.size()-1-pos); 94 ro[i].category[j].level = stringToInt(temp); 95 ro[i].category[j].have_level = true; 96 97 } 98 else { 99 ro[i].category[j].category_name = str2; 100 ro[i].category[j].have_level = false; 101 } 102 103 } 104 } 105 cin >> u; 106 for(int i = 0; i < u; i++) { 107 cin >> str1 >> m; 108 us[i].user_name = str1; 109 us[i].rname_num = m; 110 for(int j = 0; j < m; j++) { 111 cin >> str2; 112 us[i].rname[j] = str2; 113 } 114 } 115 cin >> q; 116 for(int i = 0; i < q; i++) { 117 cin >> str1 >> str2; 118 bool find_user = false; 119 for(int j = 0; j < u; j++) {//找到此用戶 120 string uname = us[j].user_name; 121 if(uname == str1) { 122 find_user = true; 123 int pos = (int)str2.find(‘:‘); 124 string cname; 125 int lev = -1; 126 if(pos != -1) { 127 cname = str2.substr(0, pos); 128 string temp = str2.substr(pos+1, str2.size()-1-pos); 129 lev = stringToInt(temp); 130 } 131 else { 132 cname = str2; 133 } 134 int len1 = us[j].rname_num; 135 int lle = -1; 136 bool cflag = false;//是否有這個權限 137 for(int k = 0; k < len1; k++) { //找此用戶的每個角色中是否有這個權限 138 int rpos = -1; 139 for(int l = 0; l < r; l++) {//找到對應角色 140 if(us[j].rname[k] == ro[l].role_name) { 141 rpos = l; 142 break; 143 } 144 } 145 int len2 = (int) ro[rpos].cname_num; 146 for (int l = 0; l < len2; l++) { 147 string cn = ro[rpos].category[l].category_name; 148 if (cname == cn) {//找到對應權限 149 cflag = true; 150 bool hl_flag = ro[rpos].category[l].have_level; 151 if (hl_flag) { lle = max(lle, ro[rpos].category[l].level); } 152 else lle = -1; 153 } 154 } 155 156 157 } 158 if(!cflag) cout << "false" << endl; 159 else { 160 if(lev == -1) { 161 if(lle == -1) cout << "true" << endl; 162 else cout << lle << endl; 163 } 164 else { 165 if(lle >= lev) cout << "true" << endl; 166 else cout << "false" << endl; 167 } 168 } 169 break; 170 } 171 172 } 173 if(!find_user) cout << "false" << endl; 174 175 } 176 return 0; 177 }
【CCF】權限查詢