1. 程式人生 > >CCF-CSP -201612-3 許可權查詢參考答案

CCF-CSP -201612-3 許可權查詢參考答案

試題名稱: 許可權查詢
一不小心半年多過去了。這半年。。。唉,不提了。反正以後不出意外還是要更新部落格的吧,希望不出。
經過半年的學習,回過頭來看當時寫的程式碼,真是渣啊。評論大哥說的很對,這次更新聽取意見了。先放上程式碼。思路啥的都在註釋裡寫了。由於系統崩了,沒法通過系統測試,不過樣例是對的。總共用了4個小時敲並調試出來。好吧,還要多練啊。
先上最新程式碼的執行效果:100分!
執行結果

/**
 * 使用者許可權查詢問題
 * 之前採用的思路是,分別建立許可權/角色/使用者三個類,使用者中儲存角色,角色中儲存許可權;查詢使用者許可權時,遍歷該使用者的所有角色的所有許可權,檢視其中是否有該許可權。。。
 * mmp,寫下我當時的這段思路後,我老臉都紅了。。。當時真的是一腔熱血的懟啊,一點演算法不懂,楞搞啊!當時因該是總是報執行超時,這麼搞不超時才怪啊。
 * 新的思路,絕對不是最好,但是至少比傻白甜1.0時期強點吧。
 *依然分為三個類:使用者/角色/許可權;但是,儲存的時候,角色只是過渡,使用者直接儲存其許可權;查詢的時候,針對某個使用者,直接查詢是否有該許可權以及許可權是否夠的問題。總的來說,應該是增加儲存時候的處理時間,但是大大減少查詢的時間。
 **/
import java.util.*; public class Main { public static Boolean debug = false; public static int level = 0;// 0 for info 1 for debug public static void main(String args[]) { //獲取資料 Scanner cin = new Scanner(System.in); // input Privission list int p = cin.nextInt(); Privilege[] arrayPrivi = new
Privilege[p]; //List<Privi> priviList = new ArrayList<Privi>(); for (int i = 0; i < p; i++) { arrayPrivi[i] = new Privilege(cin.next()); } // input role list int r = cin.nextInt(); Role[] arrayRole = new Role[r]; for (int
i = 0; i < r; i++) { String nameRole = cin.next(); int countPrivi = cin.nextInt(); Role role = new Role(nameRole, countPrivi); for (int j = 0; j < countPrivi; j++) { role.addPrivi(new Privilege(cin.next())); } arrayRole[i] = role; } //新增完角色後,檢視一下角色列表 if(Main.debug && Main.level > 1){ for(int j = 0; j < r; j++) { System.out.print("新增完角色後"); System.out.println(arrayRole[j]); } } // input user list; int u = cin.nextInt(); User[] arrayUser = new User[u]; for (int i = 0; i < u; i++) { String name = cin.next(); int countRole = cin.nextInt(); User user = new User(name); for (int j = 0; j < countRole; j++) { Role role = roleFactory(arrayRole,cin.next()); if(Main.debug && Main.level > 0){ System.out.println("Main:role to added:" + role); } user.addRole(role); //列印使用者資訊 if(Main.debug && Main.level > 0){ System.out.println("Main: user: " + user); } } arrayUser[i] = user; //新增完使用者後,檢視一下角色列表 if(Main.debug && Main.level > 0){ for(int k = 0; k < r; k++) { System.out.print("新增完一個使用者後role list: "); System.out.println(arrayRole[k]); } } //列印使用者資訊 if(Main.debug && Main.level > 0){ System.out.println("Main: 角色載入完後的user: " + user); } } // int q = cin.nextInt(); QueryHolder[] arrayQuery = new QueryHolder[q]; for (int i = 0; i < q; i++) { arrayQuery[i] = new QueryHolder(cin.next(),cin.next()); } cin.close(); if(Main.debug && Main.level > 1) System.out.println("Main:輸入結束"); //查詢開始! for(QueryHolder query : arrayQuery) { User qUser = userFactory(arrayUser, query.qUserName); if(qUser == null){ System.out.println(false); continue; } if(Main.debug && Main.level > 1) System.out.println("Main:qUser: " + qUser); int result = qUser.quaryPrivi(query.qPrivi); if(result == -2 ) System.out.println("false"); else if (result == -1) System.out.println("true"); else System.out.println("" + result); } } /**根據角色名字返回角色物件 */ private static Role roleFactory(Role[] arrayRole,String name) { for(Role role : arrayRole) { if(name.equals(role.getRoleName())) { return role; } } return null; } /**根據使用者名稱字返回使用者物件 */ private static User userFactory(User[] arrayUser,String name) { for(User user : arrayUser) { if(name.equals(user.getUserName())) { return user; } } return null; } } /**查詢引數持有類 * */ class QueryHolder { public String qUserName; public Privilege qPrivi; QueryHolder(String username, String Priviname) { this.qUserName = username; this.qPrivi = new Privilege(Priviname); } public String toString() { return "query: " + this.qUserName + " " + this.qPrivi; } } /**使用者類 * **/ class User { //使用者名稱 private String userName; //使用者擁有角色的數量 private int numRoles; //使用者擁有許可權的列表 private List<Privilege> userPrivi; /** *建構函式 **/ public User(){} public User(String userName){ this.userName = userName; //this.numRoles = numRoles; this.userPrivi = new ArrayList<Privilege>(); } /**重寫toString()方法 * **/ public String toString() { String str = "user:" + this.userName + "-"; for (Privilege privi : this.userPrivi) str += privi + " "; return str; } public String getUserName() { return this.userName; } /**查詢使用者是否具有某許可權 * 注意:許可權等級是0-9,所以 *@return -2(不具備該許可權/具備該許可權但是等級不夠); *@return -1 (具備該許可權且其具有的等級不低於給出的等級); *@return >=0的值 具備該許可權,且最高許可權為返回值; **/ public int quaryPrivi(Privilege privi) { for(Privilege p : this.userPrivi) { if(p.namePrivi.equals(privi.namePrivi)){//首先檢視是否有重名許可權: if(privi.rankPrivi <= p.rankPrivi){ //無等級許可權;直接返回0; // 有等級許可權, 給出了許可權等級且其具有的等級不低於給出的等級, 返回 0; if(p.rankPrivi == -1 || privi.rankPrivi != -1) return -1; // 有等級許可權, 但是沒給出許可權等級, 返回其擁有的最高等級許可權; else return p.rankPrivi; }else return -2; } } //沒有重名許可權 return -2; } /** * 獲取使用者的許可權集合 */ public List<Privilege> getUserPrivi(){ return this.userPrivi; } /***新增使用者的角色屬性, *直接將角色的許可權存到使用者的許可權列表中 *注意,新增的角色的時候,可能會出現,不同角色具有相同的許可權,但是許可權等級不同的情況; *對於不同的角色中,許可權名相同的部分,如果都是無等級許可權或者等級相同,由於是List,自動刪除重複的。如果是不同等級的同名許可權,則保留高等級的許可權。 **/ public void addRole(Role r) { if(Main.debug && Main.level > 0){ System.out.println("add role: user:" + this.userName); System.out.println("add role: role to added: " + r); } //獲取待新增角色的許可權列表 List<Privilege> rolePrivi = r.getRolePrivi(); //獲取該使用者的許可權數量,如果數量為0,則不會存在許可權衝突的問題,直接新增所有許可權 int numUserPrivi = this.userPrivi.size(); if(numUserPrivi == 0){ this.userPrivi.addAll(rolePrivi); return; } //如果該使用者已經有了部分許可權,則要判斷待新增的角色的許可權是否和已有的重複; //獲取待新增角色的許可權的數量 int numRolePrivi = rolePrivi.size(); for(int i = 0; i < numRolePrivi; i++) { Boolean hasSameName = false;//是否有重名許可權的標誌,每次迭代要初始化 if(Main.debug && Main.level > 1){ System.out.println("add role:" + i); System.out.println("add role: rolePrivi:i:" + rolePrivi.size()); } Privilege iPrivi = rolePrivi.get(i); for (int j = 0; j < numUserPrivi; j++) { if(Main.debug && Main.level > 1){ System.out.println("add role: userPrivi:j:" + j); System.out.println("add role: userPrivi:j:" + this.userPrivi.size()); } Privilege jPrivi = this.userPrivi.get(j); if (iPrivi.namePrivi.equals(jPrivi.namePrivi)){//有重名許可權 hasSameName = true; if(iPrivi.rankPrivi > jPrivi.rankPrivi){ //有重名許可權,且新的許可權的等級高於原許可權等級,把已有的許可權刪掉,新增新的許可權,更新使用者許可權數量 this.userPrivi.remove(j); this.userPrivi.add(iPrivi); //numUserPrivi = this.userPrivi.size(); }else{ //有重名許可權,且新的許可權的等級不高於原許可權等級,則不需要新增,把該許可權從角色許可權列表刪除,更新角色列表許可權的數量; //rolePrivi.remove(i); //numRolePrivi = rolePrivi.size(); } //如果發現了重名許可權,因為角色許可權列表肯定沒有重名許可權,且使用者許可權列表也沒有重名許可權,因此可以跳出使用者的迴圈。 break; } } //user已有的許可權和要新增的許可權都不重名:新增 if(!hasSameName){ this.userPrivi.add(iPrivi); } } //排除了所有重名可能,直接新增所有許可權 //this.userPrivi.addAll(rolePrivi); } } /**角色類 * **/ class Role { //角色名稱 private String roleName; //角色擁有的許可權列表: 二維陣列存放格式: [[許可權1名,許可權1等級],[許可權2名,許可權2等級], ...](其中,許可權名由對應的數字表示!) private List<Privilege> rolePrivilege; //許可權存放數量的計數器 //private int counterPrivilege; //public Role(){} /** *Role 建構函式 *@param roleName *@param numPrivilege 該角色擁有的許可權種類數目,由此初始化rolePrivilege **/ public Role(String roleName, int numOfPrivilege){ this.roleName = roleName; //this.counterPrivilege = 0; this.rolePrivilege = new ArrayList<Privilege>(); } public String toString() { String str = "Role:" + this.roleName + "-"; for (Privilege privi : rolePrivilege) str += privi + " "; return str; } public String getRoleName(){ return this.roleName; } public List<Privilege> getRolePrivi(){ return this.rolePrivilege; } /**為角色增加許可權; * 注意!許可權可以重複出現,如果帶等級的許可權重複出現,以等級最高的為準 *@param Privilege 許可權字串,格式:name:rank; 如 crm:1 *為降低空間,提高速度,直接將name根據對映關係記錄成數字; **/ public void addPrivi(Privilege privi) { //獲取許可權的名字 String namePrivi = privi.namePrivi; //獲取許可權的等級 int rankPrivi = privi.rankPrivi; //獲取該角色已有的許可權的數量 int numRolePrivi = this.rolePrivilege.size(); //確認是否有重複的許可權,重複的許可權儲存最高的許可權。 Boolean hasSameName = false; Privilege iPrivi = null; for (int i =0; i < numRolePrivi; i++) { //遍歷已有的許可權列表 iPrivi = this.rolePrivilege.get(i); if (iPrivi.namePrivi.equals(namePrivi)){ //有重名許可權 hasSameName = true; if(iPrivi.rankPrivi < rankPrivi){//替換列表中等級較低的許可權 this.rolePrivilege.remove(i); this.rolePrivilege.add(privi); } //如果iprivi.rankprivi >= rankprivi: //不移除、不新增,後面也不操作 break; } } if(!hasSameName) this.rolePrivilege.add(privi); } } /**許可權類 *為了提高速度,將Privilege直接儲存為陣列;[p1,p2,p3....] */ class Privilege { public String namePrivi; //許可權等級是0-9,所以-1表示為無等級許可權; public int rankPrivi; public Privilege(){} /** * */ public Privilege(String nk){ String[] privi = nk.split(":"); if(privi.length == 2){ this.namePrivi = privi[0]; this.rankPrivi = Integer.parseInt(privi[1]); }else if (privi.length == 1) { this.namePrivi = privi[0]; this.rankPrivi = -1; }else { this.namePrivi = "utility"; this.rankPrivi = -1; } } public Privilege(String namePrivi, int rankPrivi){ this.namePrivi = namePrivi; this.rankPrivi = rankPrivi; } public String toString() { if(this.rankPrivi == -1) return "privi=" + this.namePrivi; else return "privi=" + this.namePrivi + ":" + this.rankPrivi; } /** *重寫equals方法 */ public Boolean equals(Privilege p) { if(this.namePrivi.equals(p.namePrivi) && (this.rankPrivi == p.rankPrivi)) return true; return false; } }

測試的時候,自己構造一個比較好的樣例也是很重要的。題目中給出的樣例漏了幾個關鍵的資訊,如果不補上相關的資訊,自己測試不出問題,但是一提交就說錯誤。
下面是我自己的樣例,不一定就合適,但是可以做參考吧:

樣例輸入:
3
crm:2
git:3
game
4
hr 2 crm:2 crm:1
it 3 crm:1 git:1 game
dev 2 git:3 game
qa 1 git:0
4
alice 2 hr it
bob 2 it qa
charlie 1 dev
sunpro 1 qa
10
alice game
alice crm:2
bob git
bob poweroff
charlie game
charlie crm
charlie git:0
malice game
sunpro git
alice crm
樣例輸出結果:
true
true
1
false
true
false
true
false
0
2

下面的程式碼都是有問題的。沒有經過優化的:就不刪了,留著做對比吧。

我用java語言編寫,經過多次優化測試,終於符合要求。(更新:實際上,指示有一次樣例比較簡單,才符合要求了。後來再試效果也不好!)
測試記錄
下面貼出的程式碼

import java.util.Scanner;

public class Main {

    //private static Privi[] arrayPrivi;
    //private static Role[] arrayRole;
    //private static User[] arrayUser;

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        // input Privission list
        int p = cin.nextInt();
        Privi[] arrayPrivi = new Privi[p];
        //List<Privi> priviList = new ArrayList<Privi>();
        for (int i = 0; i < p; i++) {
            arrayPrivi[i] = new Privi(cin.next());
        }
        // input role list
        int r = cin.nextInt();
        Role[] arrayRole = new Role[r];
        for (int i = 0; i < r; i++) {
            String name = cin.next();
            int countrole = cin.nextInt();
            Role ro = new Role(name, countrole);
            for (int j = 0; j < countrole; j++) {
                ro.addPrivi(j, new Privi(cin.next()));
            }
            arrayRole[i] = ro;
        }
        // input user list;
        int u = cin.nextInt();
        User[] arrayUser = new User[u];
        for (int i = 0; i < u; i++) {
            String name = cin.next();
            int countrole = cin.nextInt();
            User us = new User(name,countrole);
            for (int j = 0; j < countrole; j++) {
                us.addRole(j, roleFactory(arrayRole,cin.next()));
            }
            arrayUser[i] = us;
        }
        //
        int q = cin.nextInt();
        Query[] arrayQuery = new Query[q];
        for (int i = 0; i < q; i++) {
            arrayQuery[i] = new Query(cin.next(),cin.next());
        }
        cin.close();
        //query
        //long timeBefore = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for (Query query : arrayQuery) {
            sb.append(check(query,arrayUser) + "\n");
        }
        System.out.println(sb.toString());
        //long timeAfter = System.currentTimeMillis();
        //System.out.println("use time:" + (timeAfter - timeBefore));

    }
    /**
    *
    */
    private static Role roleFactory(Role[] arrayRole,String name) {
        for(Role role : arrayRole) {
            if(name.equals(role.getName())) {
                return role;
            }
        }
        return null;
    }

    /**
    */
    private static String check(Query query,User[] arrayUser) {
        int flag = -3;
        String uname = query.qUserName;
        Privi up = query.qPrivi;
        for (User user : arrayUser) {
            flag = -3;
            if (uname.equals(user.getName())) {
                Role[] userRoleArr = user.getRoleArray();
                for (Role role : userRoleArr) {
                    Privi[] userRolePriviArr = role.getPriviArray();
                    for (Privi privi : userRolePriviArr) {
                        int temp = up.equals(privi);
                        flag = (temp > flag) ? temp : flag;
                        if(flag == -1) return "true";
                    }
                }
                break;
            }
        }
        if (flag == -2 || flag == -3) {
            return "false";
        } else
            return flag + "";
    }

    static class Query {
        public String qUserName;
        public Privi qPrivi;
        Query(String username, String Priviname) {
            this.qUserName = username;
            this.qPrivi = new Privi(Priviname);
        }
    }
}
class Privi {
    private String name;
    private int level;
    public Privi() {}

    public Privi(String per) {
        String[] p = per.split(":");
        if (p.length == 1) {
            Privi.this.name = p[0];
            Privi.this.level = -1;
        } else if (p.length == 2) {
            Privi.this.name = p[0];
            Privi.this.level = Integer.parseInt(p[1]);
        }
    }

    public String getName() {
        return this.name;
    }
    public void setName(String s) {
        this.name = s;
    }
    public int getLevel() {
        return this.level;
    }
    public void setLevel(int l) {
        this.level = l;
    }

    public int equals(Privi p) {
        if (this.name.equals(p.getName())) {
            if(this.level == -1 && this.level < p.getLevel())
                return p.getLevel();
            else if(this.level == -1 && p.getLevel() == -1)
                return -1;//bufendengji
            else if(this.level != -1 && this.level <= p.getLevel() )
                return -1;//fendengji
            else
                return -2; //
        } else
            return -2;
    }

    public String toString() {
        return this.name +(this.level != -1 ? (":" + this.level) : "");
    }
}

class Role {
    private String name;
    private int countPrivi;
    private Privi[] arrPrivi;
    //private List<Privi> priList;

    public Role() {
        this.name = "";
        //this.priList = new ArrayList<Privi>();
    }
    public Role(String n,int count) {
        this.name = n;
        this.countPrivi = count;
        this.arrPrivi = new Privi[count];
    }

    public String getName() {
        return this.name;
    }
    public void setName(String s) {
        this.name = s;
    }
    public int getPriviCount() {
        return this.arrPrivi.length;
    }
    public Privi[] getPriviArray() {
        return this.arrPrivi;
    }
    public void addPrivi(int n,Privi p) {
        this.arrPrivi[n] = p;
    }

    public String toString() {
        String s = this.name + "~" ;
        for(Privi p : this.arrPrivi) {
            s += p.toString() + "+";
        }
        return s;
    }
}


class User {
    private String name;
    private int countRole;
    private Role[] arrRole;

    public User() {
        this.name = "";
        //this.roleList = new ArrayList<Role>();
    }
    public User(String name, int count) {
        this.name = name;
        this.countRole = count;
        this.arrRole = new Role[count];
    }

    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Role[] getRoleArray() {
        return this.arrRole;
    }
    public void addRole(int n, Role role) {
        this.arrRole[n] = role;
    }
    public String toString() {
        String s = name + "~";
        for(Role role : arrRole) {
            s += role.toString() + "+";
        }
        return s;
    }
}

下面的是最早的版本,執行結果正確,但是執行超時。可以與上面進行對比。主要優化點有:
(1)將List改為Array;
(2)將全域性變數改為區域性變數;
(3)輸出採用StringBuilder;
(4)check()方法中,進一步精確了終止迴圈的時間;這應該是最顯著的改善點。

import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    private static List<Privi> priviList = new ArrayList<Privi>();
    private static List<Role> roleList = new ArrayList<Role>();
    private static List<User> userList = new ArrayList<User>();

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        // input Privilege list
        int p = cin.nextInt();
        for (int i = 0; i < p; i++) {
            priviList.add(new Privi(cin.next()));
        }
        // input role list
        int r = cin.nextInt();
        for (int i = 0; i < r; i++) {
            //
            Role ro = new Role(cin.next());
            int pn = cin.nextInt();
            for (int j = 0; j < pn; j++) {
                ro.addPrivi(new Privi(cin.next()));
            }
            roleList.add(ro);
        }
        // input user list;
        int u = cin.nextInt();
        for (int i = 0; i < u; i++) {
            User us = new User(cin.next());
            int rn = cin.nextInt();
            for (int j = 0; j < rn; j++) {
                us.addRole(roleFactory(cin.next()));
            }
            userList.add(us);
        }
        //
        int q = cin.nextInt();
        List<Query> queryList = new ArrayList<Query>();
        for (int i = 0; i < q; i++) {
            Query qu = new Query(cin.next(),cin.next());
            queryList.add(qu);
        }
        //query 
        for (Query query : queryList) {
            System.out.println(check(query));
        }
        cin.close();
    }
    /**
    *
    */
    private static Role roleFactory(String name) {
        for(Role role : roleList) {
            if(name.equals(role.getName())) {
                return role;
            }
        }
        return null;
    }

    /**
    */
    private static String check(Query query) {
        int flag = -3;
        for (User user : userList) {
            flag = -3;
            if (query.qUserName.equals(user.getName())) {
                List<Role> userRoleList = user.getRoleList();
                for (Role role : userRoleList) {
                    List<Privi> userRolePriviList = role.getPriviList();
                    for (Privi privi : userRolePriviList) {
                        int temp = query.qPrivi.equals(privi);
                        flag = (temp > flag) ? temp : flag;
                        if(flag == -1) break;
                    }
                    if(flag == -1) break;
                }
            }
            if (flag != -3) {
                break;
            }
        }
        if (flag == -2 || flag == -3) {
            return "false";
        } else if(flag == -1) {
            return "true";
        } else
            return flag + "";
    }

    static class Query {
        public String qUserName;
        public Privi qPrivi;
        Query() {
            qUserName = "";
            qPrivi = new Privi();
        }
        Query(String username) {
            this.qUserName = username;
            this.qPrivi = new Privi();
        }
        Query(String username, String Priviname) {
            this.qUserName = username;
            this.qPrivi = new Privi(Priviname);
        }
    }

    static class Privi {
        private String name;
        private int level;
        public Privi() {}

        public Privi(String per) {
            String[] p = per.split(":");
            if (p.length == 1) {
                Privi.this.name = p[0];
                Privi.this.level = -1;
            } else if (p.length == 2) {
                Privi.this.name = p[0];
                Privi.this.level = Integer.parseInt(p[1]);
            }
        }

        public String getName() {
            return this.name;
        }
        public void setName(String s) {
            this.name = s;
        }
        public int getLevel() {
            return this.level;
        }
        public void setLevel(int l) {
            this.level = l;
        }

        public int equals(Privi p) {
            if (this.name.equals(p.getName())) {
                if(this.level == -1 && this.level < p.getLevel())
                    return p.getLevel();
                else if(this.level == -1 && p.getLevel() == -1)
                    return -1;//bufendengji
                else if(this.level != -1 && this.level <= p.getLevel() )
                    return -1;//fendengji 
                else
                    return -2; //
            } else
                return -2;
        }

        public String toString() {
            return this.name +(this.level != -1 ? (":" + this.level) : "");
        }
    }

    static class Role {
        private String name;
        private List<Privi> priList;

        public Role() {
            this.name = "";
            this.priList = new ArrayList<Privi>();
        }
        public Role(String n) {
            this.name = n;
            this.priList = new ArrayList<Privi>();
        }

        public String getName() {
            return this.name;
        }
        public void setName(String s) {
            this.name = s;
        }
        public int getPriviCount() {
            return this.priList.size();
        }
        public List<Privi> getPriviList() {
            return this.priList;
        }
        public void addPrivi(Privi p) {
            this.priList.add(p);
        }

        public String toString() {
            String s = this.name + "~" ;
            for(Privi p : this.priList) {
                s += p.toString() + "+";
            }
            return s;
        }
    }


    static class User {
        private String name;
        private List<Role> roleList;

        public User() {
            this.name = "";
            this.roleList = new ArrayList<Role>();
        }
        public User(String name) {
            this.name = name;
            this.roleList = new ArrayList<Role>();
        }

        public String getName() {
            return this.name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public List<Role> getRoleList() {
            return this.roleList;
        }
        public void addRole(Role role) {
            this.roleList.add(role);
        }
        public String toString() {
            String s = name + "~";
            for(Role role : roleList) {
                s += role.toString() + "+";
            }
            return s;
        }
    }
}