Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

최's 먹공로그

BOJ25240 가희와 파일 탐색기2 본문

Pro감옥

BOJ25240 가희와 파일 탐색기2

ChoiSH313 2022. 10. 1. 14:59

<문제 요약>

https://www.acmicpc.net/problem/25240

 

25240번: 가희와 파일 탐색기 2

Q개의 질문에 대해, 연산이 성공하면 1을 실패하면 0을 출력해 주세요. 각 질문에 대한 답은 한 줄에 하나씩 출력해 주세요.

www.acmicpc.net

(1) 3개의 숫자 중

첫번 째 숫자 : 파일을 소유하고 있는 유저가 어떤 권한을 가지고 있는지를 나타냄

두번 째 숫자 : 파일을 소유하고 있는 그룹이 어떤 권한을 가지고 있는지

세번 째 숫자 : 파일을 소유하고 있는 그룹에 속하지 않고, 파일을 소유하고 있는 유저가 아닌 경우 어떤 권한을 가지고 있는지

(2) 입력
-. 유저에 대한 정보 U, 파일에 대한 정보 F

-. U개의 유저 정보
USER_NAME
USER_NAME, USER_GROUPS 유저가 속한 그룹이 여러 개라면 ,로 구분
USER_NAME은 자동으로 그룹 이름이 USER_NAME 인 그룹에 속함
※ 유저가 속한 그룹들에 대한 정보에 USER_NAME이 주어지지 않더라도 그룹 이름이 USER_NAME인 그룹에 속함

-. 파일 정보
FIME_NAME  FIME_PERMISSION  OWNER  OWNED_GROUP
파일이름      파일 권한             소유자   소유그룹

-. 질문정보
질문 개수 Q
USER_NAME  FILE_NAME  OPERATION(R읽기,W수정,X실행)

(3) 출력
Q개의 질문에 대해 연산이 성공하면 1 실패하면 0 각 질문에 대한 답은 한 줄에 하나씩 출력

 

<풀이흐름, Source Code>

(1) User정보는 HashMap<String UserName, HashSet<String GroupName>>에 저장

File정보는 HashMap<String FileName, FileInfo>에 저장한다. FileInfo는 권한, 소유자 이름, 소유그룹 이름을 갖는다.

(2) UserName과 GroupName을 입력 받아서 UserList에 넣는다. 이 때, Group이 여러개면 ','로 구분된다는 점과 GroupName이 없으면 UserName = GroupName이라는 점 그리고 GroupName이 있어도 UserName이 GroupName도 된다는 점을 주의한다.

(3) FileName과 FileInfo를 입력 받아서 FileList에 넣어준다.

파일에 대한 권한의 경우 754 이런식으로 3글자로 들어오는데 이를 2진수로 검사해줄 예정

숫자 권한 2진수
0 아무것도 할 수 없음 0000
1→X 실행 권한이 있음 0001
2→W 수정 권한이 있음 0010
3 실행 권한과 수정 권한이 있음 0011
4→R 읽기 권한이 있음 0100
5 읽기와 실행 권한이 있음 0101
6 읽기와 수정 권한이 있음 0110
7 읽기와 실행, 수정 권한이 있음 0111

754인 경우 arr_permission[OWNER = 0] = 7, arr_permission[GROUP = 1] = 5, arr_permission[GUEST = 2] = 4와 같이 저장 해준다.

(4) 질문은 UserName FileName Command 순서로 들어오는데 User가 File에 대해 Command를 할 수 있으면 1 없으면 0 이니깐 일단 Command를 숫자화 한다.(위 표 참고)

(5) 이제 순서대로 FileList에 소유자이름과 질문의 UserName을 비교 → FileList의 그룹이름과 UserName의 GroupName을 비교해서 권한을 & 연산으로 계산 해준다. 위 두개의 비교에서 같은 이름이 없으면 그냥 GUEST의 권한과 비교한다. 최종 권한이 질문의 권한과 동일하면 파일에 대한 권한이 있어서 return 1, 아니면 return 0

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.StringTokenizer;

public class BOJ25240_가희 {

	private static class fileInfo {
		String ownerName;
		String ownerGroupName;
		int[] arr_permission = new int[3];

		fileInfo(int permission, String ownerName, String ownerGroupName) {
			arr_permission[GUEST] = permission % 10;
			permission /= 10;
			arr_permission[GROUP] = permission % 10;
			permission /= 10;
			arr_permission[OWNER] = permission % 10;
			this.ownerName = ownerName;
			this.ownerGroupName = ownerGroupName;
		}
	}

	static int U, F, Q;
	static final int OWNER = 0, GROUP = 1, GUEST = 2;
	static HashMap<String, HashSet<String>> userList = new HashMap<String, HashSet<String>>();
	static HashMap<String, fileInfo> fileList = new HashMap<String, fileInfo>();
	static StringBuilder sb = new StringBuilder();

	public static void main(String[] args) throws IOException {
		input();
	}

	private static void input() throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		U = Integer.parseInt(st.nextToken());
		F = Integer.parseInt(st.nextToken());
		for (int iu = 0; iu < U; iu++) {
			st = new StringTokenizer(br.readLine(), " ");
			String strUserName = "";
			String strGroupName = "";
			if (st.countTokens() == 2) {
				strUserName = st.nextToken();
				strGroupName = st.nextToken();
			} else if (st.countTokens() == 1) {
				strUserName = st.nextToken();
				strGroupName = strUserName;
			}
			if (!userList.containsKey(strUserName)) {
				userList.put(strUserName, new HashSet<String>());
			}
			userList.get(strUserName).add(strUserName);// 사용자도 그룹임
			String[] strTempGroupName = strGroupName.split(",");
			for (String temp : strTempGroupName) {
				userList.get(strUserName).add(temp);
			}
		}
		for (int iif = 0; iif < F; iif++) {
			st = new StringTokenizer(br.readLine(), " ");
			String strFileName = st.nextToken();
			fileInfo fi = new fileInfo(Integer.parseInt(st.nextToken()), st.nextToken(), st.nextToken());
			fileList.put(strFileName, fi);
		}
		st = new StringTokenizer(br.readLine());
		Q = Integer.parseInt(st.nextToken());
		for (int qi = 0; qi < Q; qi++) {
			st = new StringTokenizer(br.readLine(), " ");
			int result = cal(st.nextToken(), st.nextToken(), st.nextToken());
			sb.append(result);
			sb.append("\n");
		}
		System.out.print(sb.toString());
	}

	private static int cal(String userName, String fileName, String oper) {
		int iPermission = 0;
		if (oper.equals("X"))
			iPermission = 1;
		else if (oper.equals("W"))
			iPermission = 2;
		else if (oper.equals("R"))
			iPermission = 4;

		int lastPermission = 0;
		if (fileList.containsKey(fileName)) {
			fileInfo fi = fileList.get(fileName);
			String strownerName = fi.ownerName;
			String strownerGroupName = fi.ownerGroupName;
			int[] arrPermission = fi.arr_permission;
			if (userName.equals(strownerName)) {
				lastPermission = iPermission & arrPermission[OWNER];
			} else if (isGroup(userName, strownerGroupName)) {
				lastPermission = iPermission & arrPermission[GROUP];
			} else {
				lastPermission = iPermission & arrPermission[GUEST];
			}
			if (lastPermission == iPermission)
				return 1;
			else
				return 0;
		}
		return 0;
	}

	private static boolean isGroup(String struserName, String strownerGroupName) {
		for (String tempGroupName : userList.get(struserName)) {
			if (tempGroupName.equals(strownerGroupName)) {
				return true;
			}
		}
		return false;
	}
}

 

<문제 Issue>

(1) UserName이 GroupName도 될 수 있다. GroupName이 있어도 UserName은 GroupName이 된다.

입력이 a b,c,d 인 경우 User a가 속한 그룹은 b,c,d가 아니라 a,b,c,d 이다.

 

<중요 정리>

(1) HashMap과 HashSet 사용

HashMap<String, String> 이런식으로도 쓸 수 있지만 HashMap<String, HashSet<>> 이런식으로도 사용 가능 하다.

(2) 파일 권한 비교 비트연산

'Pro감옥' 카테고리의 다른 글

BOJ5052 전화번호 목록  (4) 2022.10.06
BOJ1202 보석도둑  (0) 2022.09.29
[자료구조] 힙(heap)  (10) 2021.04.29