본문 바로가기

알고리즘 문제 풀이/Baekjoon

5052 - 전화번호 목록

반응형
SMALL

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

 

5052번: 전화번호 목록

문제 전화번호 목록이 주어진다. 이때, 이 목록이 일관성이 있는지 없는지를 구하는 프로그램을 작성하시오. 전화번호 목록이 일관성을 유지하려면, 한 번호가 다른 번호의 접두어인 경우가 없어야 한다. 예를 들어, 전화번호 목록이 아래와 같은 경우를 생각해보자 긴급전화: 911 상근: 97 625 999 선영: 91 12 54 26 이 경우에 선영이에게 전화를 걸 수 있는 방법이 없다. 전화기를 들고 선영이 번호의 처음 세 자리를 누르는 순간 바로 긴급전화가

www.acmicpc.net

문자열 알고리즘, 자료구조엔 투 톱이 있습니다. (주관적인 생각입니다)

 

해시(hash)와 트라이(Trie)가 바로 그 것인데요.

 

해시는 여러분들이 흔히 사용하는 Python의 dictionary라고 생각하면 됩니다. (제가 파이썬 유저라 ㅎㅎ)

 

그렇다면 트라이는 무엇일까요?

 

트라이 자료구조는 문자열 검색에서 많이 사용되는 자료구조입니다. (알고리즘? 자료구조? 어떻게 불러야 할 지 애매하기에 자료구조라고 명하겠습니다)

 

제가 알아본 바로는 저희 자동 검색기능 있잖아요? '네'까지만 쳐도 '네이버'가 나오는 검색창, 그걸 트라이로 구현할 수 있다고 하네요.

 

이처럼 실생활에서도 많이 쓰는 트라이기에 트라이의 가장 기본 문제인 전화번호 목록을 풀어봤습니다.

 

트라이라 함은 한 글자씩 노드를 타고내려 가면서 그 다음 글자가 있는지를 확인하는 자료구조입니다. 또한, 단어의 끝에 endOfWord와 같은 boolean 계수를 추가하면서 그 단어가 끝인지 아닌지를 파악한다면 '119', '1191'과 같은 중복되는 숫자가 있는 경우에도 저장을 할 수 있습니다.

 

저 역시 위와 같은 방법으로 풀었습니다. 노드에는 endOfWord로 글자가 끝나는 지점을 표시하고 0 ~ 9까지의 숫자 배열을 두어서 다음 노드로 넘어갈 수 있는 다리를 놓았습니다. 만약 word 배열의 값에 주소값이 있다면 그 인덱스 번호는 다음 노드로 넘어갈 수 있는 것이지요. 마치 위의 트리 그림과 유사하게요.

 

이처럼 문제를 해결한다면 누구나 쉽게 풀 수 있는 문제라 생각합니다.

 

하지만, 진정한 어려움은 트라이를 다른데 접목시키는 거겠죠..?

 

흑흑

#include <stdio.h>
#include <malloc.h>

typedef struct _node {
	int endOfWord;
	struct _node* word[10];
} Node;

Node* makeNode(void) {
	Node* temp = (Node*)malloc(sizeof(Node));
	temp->endOfWord = 0;
	for (int i = 0; i < 10; i++) temp->word[i] = 0;
	return temp;
}

int T, N;
char number[11];
Node* trie;

int triePush(const char* number) {
	int idx = 0, num, boolean = 0;
	Node* root = trie;
	Node* temp;
	while (number[idx] != '\0' && !root->endOfWord) {
		num = (int)number[idx] - '0';
		if (!root->word[num]) {
			temp = makeNode();
			root->word[num] = temp;
			boolean = 1;
		}
		root = root->word[num];
		idx++;
	}
	if (!boolean) return 0;
	root->endOfWord = 1;
	return 1;
}

int main(void) {
	scanf("%d", &T);
	for (int t = 0; t < T; t++) {
		int result = 1;
		trie = makeNode();
		scanf("%d", &N);
		for (int n = 0; n < N; n++) {
			scanf("%s", number);
			if (triePush(number)) continue;
			else result = 0;
		}
		if (result) printf("YES\n");
		else printf("NO\n");
	}
}

이상 5052 - 전화번호 목록였습니다. ^_^

반응형
LIST

'알고리즘 문제 풀이 > Baekjoon' 카테고리의 다른 글

14425 - 문자열 집합 (Trie 풀이)  (0) 2020.02.06
12791 - Starman  (0) 2020.02.04
1920 - 수 찾기  (0) 2020.01.29
1717 - 집합의 표현  (0) 2019.11.18
1976 - 여행 가자  (0) 2019.11.17