티스토리 뷰

http://www.jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=1697&sca=5030

 

JUNGOL | 순서찾기 > 문제은행

아주 먼 옛날 정올국이라는 국가가 있었다. 한재는 정올국에 대해 연구를 하는 학자인데,  어느날 정올국의 문서로 추측되는 문서가 발견되었다. 한재는 정올국이 사용하던 문자가 현재의 영어와 같다는 사실을 알고 있었으나,  사용되는 알파벳의 순서가 영어와 같이 "abc...z"순이 아니라는 사실을 본 문서를 통해 알게 되었다. 허나 정확한 순서를 알수가 없었고, 이에 대해 정올국에서 사용하던 알파벳의 정확한 순서를 알고자 시도하였지만  목표하던 바에 도달하지

www.jungol.co.kr

전형적인 순서를 찾기 위한 위상정렬 문제이다.

여기서 고민할 건 그래프를 어떻게 만드느냐 정도인듯..

 

같은 위치에 있는 단어를 비교하면서 그래프 형태로 나타내면 된다.

 

위상정렬을 통해 들어오는 간선이 0인 경우를 큐에 넣으면서 순서를 찾아가면 됨

큐가 노드만큼 못돌면 없는 케이스고

큐가 중간에 2개 이상 들어가면 순서가 하나가 아닌 케이스

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
	private static int T;
	private static int N;
	private static int numOfNode;
	private static String[] W;
	private static ArrayList[] G;
	private static int[] indegree;

	final private static int NUM_OF_ALPHABET= 26;
	final private static String CANNOT = "!";
	final private static String MANY = "?";

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

		T = Integer.parseInt(br.readLine());
		for (int test_case = 1; test_case <= T; test_case++) {

			N = Integer.parseInt(br.readLine());

			// 초기화
			W = new String[N];
			G = new ArrayList[NUM_OF_ALPHABET];
			indegree = new int[NUM_OF_ALPHABET];
			numOfNode = 0;
			Arrays.fill(indegree, -1);
			
			for (int i = 0; i < N; i++) {
				W[i] = br.readLine();
			}
			makeGraph();			
			String res = topologicalSort();
			bw.write(String.format("%s\n", res));
			bw.flush();
		}
		bw.close();
	}

	private static void makeGraph() {
		for (int i = 0; i < N - 1; i++) {
			String now = W[i];
			String next = W[i+1];
			
			// 단어 위아래로 훑으면서 순서대로 그래프 그려감
			for(int j = 0, len = Math.min(now.length(), next.length()) ; j < len; j++) {
				int nowIdx = charToInteger(now.charAt(j));
				int nextIdx = charToInteger(next.charAt(j));
				
				if (nowIdx == nextIdx) continue;
				if (G[nowIdx] == null) G[nowIdx] = new ArrayList<Integer>();
				initIndegree(new int[]{nowIdx, nextIdx});
				
				G[nowIdx].add(nextIdx);
				indegree[nextIdx]++;
				break;
			}
		}
		// 같은 위치에 같은 단어가 있으면 여기서 순서대로 그래프 생성
		// ex) ula uka 있으면 u로 시작하니까 뒤에 l -> k 라는 순서를 알 수 있음 이 대로 그래프 그림
	}

	private static String topologicalSort() {
		// 그래프 그린대로 위상정렬 수행,
		// inbound==0 인 경우를 찾아가면서 N개 뽑아낼 수 있으면
		StringBuilder sb = new StringBuilder();
		Queue<Integer> q = new LinkedList<Integer>();
		
		for(int i = 0; i < numOfNode;i++) {
			
			for(int n = 0;n < NUM_OF_ALPHABET;n++) {
				if(indegree[n] == 0) {
					q.add(n);
				}
			}
			// 큐가 노드 개수만큼 안돌았는데 비면 순서 정할 수 없음
			if(q.isEmpty()) return CANNOT;
			
			// 큐가 2개 이상이면 경우의 수가 2개 이상이라는거임
			if(q.size() > 1) return MANY;
			
			// 
			int now = q.remove();
			sb.append(integerToChar(now));
			indegree[now]--;
			
			if(G[now] == null || G[now].size() == 0) continue ; 
			for (int j = 0, len = G[now].size(); j < len; j++) {
				int next =(int)G[now].get(j); 
				indegree[next]--;
			}
		}
		
		return sb.toString();
	}
	private static void initIndegree(int[] indices) {
		for(int idx : indices) {
			if(indegree[idx] != -1) continue;
			indegree[idx]= 0;
			numOfNode++;
		}
	}
	private static int charToInteger(char c) {
		return c - 'a';
	}
	
	private static char integerToChar(int i) {
		return (char) (i + 'a');
	}
	

	private static void printGraph() {
		System.out.println("NUM : " + numOfNode);
		System.out.println(Arrays.toString(indegree));
		for(int i = 0;i < NUM_OF_ALPHABET; i++) {
			if(G[i] != null) {
				char u = integerToChar(i);
				System.out.print(u + " -> ");
				for(int j= 0; j < G[i].size(); j++) {
					char v = integerToChar((int)G[i].get(j));
					System.out.print(v + ", ");
				}
				System.out.println();
			}
		}
	}
}
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   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
글 보관함