- 문제
- 링크 : https://www.acmicpc.net/problem/22861
- 폴더의 파일을 정리 후 쿼리문을 통해서 파일 정보 확인
- 조건
- 같은 폴더 존재 X
- 같은 폴더 내에서 같은 파일명 존재 X
- 같은 이름의 파일은 서로 같은 내용을 가지고 있음
- 모든 폴더는 하나 이상의 파일을 가지고 있음
- 입력
- 첫번째 줄
- N : main 폴더 안에 있는 폴더의 총 개수 (1 ≤ N ≤1,000)
- M : 파일의 총 개수 (1 ≤ M ≤ 1,000)
- 두번째 줄 ~ (N+M+1)번째 줄
- P : 상위 폴더의 이름 (1 ≤ |P| ≤ 10)
- F : 폴더 또는 파일의 이름 (1 ≤ |F| ≤ 10)
- C : 폴더 = 1, 파일 = 0
- (N+M+2)번째 줄
- K : 옮기는 횟수 (0 ≤ K ≤ 1,000)
- (N+M+3)번째 줄 ~ (N+M+K+3)번째 줄
- 이동 전 폴더 경로 A
- 이동할 폴더 경로 B
- 경로 A의 하위 파일을 경로 B의 하위 파일로 이동
- (N+M+K+4)번째 줄
- Q : 쿼리의 개수 (1 ≤ Q ≤ 1,000)
- (N+M+K+5)번째 줄 ~ (N+M+K+Q+5)번째 줄
- 파일의 쿼리
- 첫번째 줄
- 출력
- 쿼리 순서대로 폴더 하위에 있는 파일 종류의 개수와 파일의 총 개수
- 파일 종류의 개수 : 같은 이름의 파일이 있는 경우 → 같은 종류로 포함
- 파일의 총 개수 : 같은 이름의 파일이 있는 경우 → 하나로 계산하지 않음
- 쿼리 순서대로 폴더 하위에 있는 파일 종류의 개수와 파일의 총 개수
- 찾아낸 규칙
- 로직 1)
import java.lang.*;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;
public class Main {
// 폴더를 입력받으면, 폴더의 쿼리 반환
static String findKey(String key, Map<String, Set<String>> map) {
// key가 포함된 쿼리가 있는 것만 필터링
List<String> keys = map.keySet().stream().filter(s -> s.contains(key)).collect(Collectors.toList());
// 상위 폴더가 없는 경우
if(keys.isEmpty()) return "";
// 상위 폴더가 있는 경우
String[] keyArray = keys.get(0).split("/");
String query = keyArray[0];
if(!keyArray[0].equals(key)) {
for(int i=1; i<keyArray.length; i++) {
query = query + "/" +keyArray[i];
if(keyArray[i].equals(key)) break;
}
}
return query;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Map<String, Set<String>> map = new HashMap<>();
Queue<String> queueFolder = new LinkedList<>();
Queue<String> queuefile = new LinkedList<>();
// 폴더와 파일의 개수 합
int count = sc.nextInt() + sc.nextInt();
for(int i=0; i<count; i++) {
String P = sc.next(); // 상위 폴더 이름
String F = sc.next(); // 폴더 또는 파일 이름
int C = sc.nextInt(); // 1 = 폴더, 0 = 파일
String highFolder = findKey(P, map); // 상위 폴더의 쿼리 찾기
// 폴더인 경우
if(C == 1) {
if(P.equals("main")) { // 상위 폴더가 없는 경우
map.put(P+"/"+F, new HashSet<>());
} else { // 상위 폴더가 있는 경우
if(map.get(highFolder) == null) {
queueFolder.add(P);
queueFolder.add(F);
} else map.put(highFolder+"/"+F, new HashSet<>());
}
} else { // 파일인 경우
if(map.get(highFolder) == null) {
queuefile.add(P);
queuefile.add(F);
} else map.get(highFolder).add(F);
}
}
// 폴더인 경우
while(!queueFolder.isEmpty()) {
String P = queueFolder.poll();
String F = queueFolder.poll();
String highFolder = findKey(P, map);
if(map.get(highFolder) == null) {
queueFolder.add(P);
queueFolder.add(F);
} else map.put(highFolder+"/"+F, new HashSet<>());
}
// 파일인 경우
while(!queuefile.isEmpty()) {
String P = queuefile.poll();
String F = queuefile.poll();
String highFolder = findKey(P, map);
if(map.get(highFolder) == null) {
queuefile.add(P);
queuefile.add(F);
} else map.get(highFolder).add(F);
}
// 파일 이동
count = sc.nextInt();
for(int i=0; i<count; i++) {
// 폴더A와 폴더B의 폴더 경로
String A = sc.next();
String B = sc.next();
// 폴더A, 폴더B의 value 찾기
Set<String> folderA = map.get(A);
Set<String> folderB = map.get(B);
// 폴더A의 파일을 폴더B로 이동 및 폴더A 삭제
if(folderA != null) {
throw new NumberFormatException();
}
folderB.addAll(folderA);
map.remove(A, folderA);
// 폴더A 내에 있는 폴더의 경로 변경
List<String> lowFolders = map.keySet().stream().filter(s -> s.contains(A)).collect(Collectors.toList()); // 폴더A 안에 있는 폴더명 검색
for(int j=0; j<lowFolders.size(); j++) {
map.put(lowFolders.get(j).replace(A, B), map.get(lowFolders.get(j)));
map.remove(lowFolders.get(j));
}
}
// 폴더 내 파일 종류와 개수 출력하기
count = sc.nextInt();
for(int i=0; i<count; i++) {
Set<String> fileType = new HashSet<>(); // 파일의 종류
List<String> fileCount = new ArrayList<>(); // 파일의 개수
String findFolder = sc.next(); // 탐색할 폴더
List<String> findFolders = map.keySet().stream().filter(s -> s.contains(findFolder)).collect(Collectors.toList()); // 탐색할 폴더 안에 있는 폴더명 검색
for(int j=0; j<findFolders.size(); j++) {
Set<String> values = map.get(findFolders.get(j));
// 탐색할 폴더 내부에 있는 파일 추가하기
if(values != null) fileType.addAll(values);
if(values != null) fileCount.addAll(values);
}
System.out.println(fileType.size() + " " + fileCount.size());
}
}
}
'코딩테스트 > 백준' 카테고리의 다른 글
[Java] 백준 21758번 - 꿀 따기 (0) | 2023.05.05 |
---|---|
[Java] 백준 1167번 - 트리의 지름 (0) | 2023.05.02 |
[Java] 백준 20207번 - 달력 (0) | 2023.04.04 |
[Java] 백준 15961번 - 회전 초밥 (0) | 2023.04.03 |
[Java] 백준 14925번 - 목장 건설하기 (1) | 2023.03.25 |