1. 程式人生 > >【CCF】權限查詢

【CCF】權限查詢

個數 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% 的評測用例權限都是不分等級的,查詢也都不帶等級 分析 題目很簡單,思路很清晰,就是代碼量有點大,寫著寫著容易混亂。
  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】權限查詢