출처 : 백준 #5052
시간 제한 | 메모리 제한 |
---|---|
1초 | 256MB |
전화번호 목록이 주어진다. 이때, 이 목록이 일관성이 있는지 없는지를 구하는 프로그램을 작성하시오.
전화번호 목록이 일관성을 유지하려면, 한 번호가 다른 번호의 접두어인 경우가 없어야 한다.
예를 들어, 전화번호 목록이 아래와 같은 경우를 생각해보자
첫째 줄에 테스트 케이스의 개수 t가 주어진다. (1 ≤ t ≤ 50) 각 테스트 케이스의 첫째 줄에는 전화번호의 수 n이 주어진다. (1 ≤ n ≤ 10000) 다음 n개의 줄에는 목록에 포함되어 있는 전화번호가 하나씩 주어진다. 전화번호의 길이는 길어야 10자리이며, 목록에 있는 두 전화번호가 같은 경우는 없다.
각 테스트 케이스에 대해서, 일관성 있는 목록인 경우에는 YES, 아닌 경우에는 NO를 출력한다.
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
NO
YES
처음에는 단순히 이중 for문을 통해 짧은 문자열이 긴 문자열의 앞 부분에 속하는지 여부를 판단했다.
당연히 오답이다. (시간초과)
도저히 생각이 안나서 질문검색 페이지를 보니 Trie? 알고리즘을 통해 풀었다고 했다.
사실 해당 알고리즘을 찾아서 완벽히 숙지 후 풀어도 됐겠지만, 자존심이 허락하지 않았다.
따라서 트리로 접근한다는 사실만을 캐치하고 내 스스로 코드를 짜보았다.
핵심은 문자열이 끝날 때마다 flag를 심어주어서 다른 문자열을 트리에 넣을 때 해당 flag를 지나치는지 여부로 판단하는 것이다.
설명이 어렵다면 아래의 그림을 참고하여 보자.
우선 Node
클래스에 next 공간을 만들어 주었다.
Graph
클래스에서는 탐색의 처음에 사용할 adjList를 선언했고, 마찬가지로 0~9까지 올 수 있다고 판단하여 10만큼의 공간을 할당했다.
insertEdge
함수를 통해 만약 첫 숫자가 없을 경우 노드를 생성하여 해당 숫자를 인덱스로 가진 곳에 넣어주었다.이렇게 하면 1개의 번호일 때 체클르 못해주어서 1개의 문자열이 들어올 때 flag를 심어주는 if문도 넣었다.
문자열 문제를 요즘 많이 풀면서 느낀 것은 다양한 자료구조를 통해 시각화를 할 수 있거나 반대 방향으로 탐색하면 조금 더 쉽게 문제를 접근할 수 있었다는 사실이다.
많이 부족했지만 그래도 끝까지 답을 안보고 스스로 코드를 작성해보는 계기가 되었고, 앞으로는 다양한 자료구조도 함께 생각해보는 사람이 되어야겠다.
# 백준 5052번 전화번호 목록
from sys import stdin
input = stdin.readline
class Node:
def __init__(self, node):
self.node = node
self.next = [None]*10
self.flag = False
class Graph:
def __init__(self):
self.adjList = [0] * 10
def insertEdge(self, string):
x = int(string[0])
if self.adjList[x] == 0:
new = Node(x)
self.adjList[x] = new
temp = self.adjList[x]
if len(string) == 1:
temp.flag = True
else:
if temp.flag == True:
return False
for i in range(1, len(string)):
S = int(string[i])
if temp.next[S] is None:
w = Node(S)
temp.next[S] = w
else:
if temp.next[S].flag != False:
return False
if i == len(string)-1: # 마지막 원소라면
temp.next[S].flag = True
temp = temp.next[S]
return True
def solution(phonebook):
phonebook.sort()
n = len(phonebook)
g = Graph()
for number in phonebook:
result = g.insertEdge(number)
if result != True:
return "NO"
return "YES"
# 시간 초과
# for i in range(n):
# for j in range(i+1, n):
# m = len(phonebook[i])
# if len(phonebook[i]) < len(phonebook[j]):
# if phonebook[j][:m] == phonebook[i]:
# return "NO"
# return "YES"
t = int(input())
for x in range(t):
n = int(input())
phonebook = []
for i in range(n):
phonebook.append(input().rstrip())
print(solution(phonebook))