BAEKJOON #5052번 전화번호 목록 (문자열) - python
전화번호 목록
출처 : 백준 #5052
시간 제한 | 메모리 제한 |
---|---|
1초 | 256MB |
문제
전화번호 목록이 주어진다. 이때, 이 목록이 일관성이 있는지 없는지를 구하는 프로그램을 작성하시오.
전화번호 목록이 일관성을 유지하려면, 한 번호가 다른 번호의 접두어인 경우가 없어야 한다.
예를 들어, 전화번호 목록이 아래와 같은 경우를 생각해보자
- 긴급전화: 911
- 상근: 97 625 999
- 선영: 91 12 54 26
이 경우에 선영이에게 전화를 걸 수 있는 방법이 없다. 전화기를 들고 선영이 번호의 처음 세 자리를 누르는 순간 바로 긴급전화가 걸리기 때문이다. 따라서, 이 목록은 일관성이 없는 목록이다.
입력
첫째 줄에 테스트 케이스의 개수 t가 주어진다. (1 ≤ t ≤ 50) 각 테스트 케이스의 첫째 줄에는 전화번호의 수 n이 주어진다. (1 ≤ n ≤ 10000) 다음 n개의 줄에는 목록에 포함되어 있는 전화번호가 하나씩 주어진다. 전화번호의 길이는 길어야 10자리이며, 목록에 있는 두 전화번호가 같은 경우는 없다.
출력
각 테스트 케이스에 대해서, 일관성 있는 목록인 경우에는 YES, 아닌 경우에는 NO를 출력한다.
입출력 예시
예제 입력 1
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
예제 출력 1
NO
YES
풀이
생각 및 풀이 설명
-
처음에는 단순히 이중 for문을 통해 짧은 문자열이 긴 문자열의 앞 부분에 속하는지 여부를 판단했다.
-
당연히 오답이다. (시간초과)
-
도저히 생각이 안나서 질문검색 페이지를 보니 Trie? 알고리즘을 통해 풀었다고 했다.
-
사실 해당 알고리즘을 찾아서 완벽히 숙지 후 풀어도 됐겠지만, 자존심이 허락하지 않았다.
-
따라서 트리로 접근한다는 사실만을 캐치하고 내 스스로 코드를 짜보았다.
-
핵심은 문자열이 끝날 때마다 flag를 심어주어서 다른 문자열을 트리에 넣을 때 해당 flag를 지나치는지 여부로 판단하는 것이다.
-
설명이 어렵다면 아래의 그림을 참고하여 보자.
-
우선
Node
클래스에 next 공간을 만들어 주었다.- 번호는 0~9까지 있을 수 있으므로 공간은 10씩 할당하였다.
- 또한 flag를 심어서 초기값을 False로 놓았다.
-
Graph
클래스에서는 탐색의 처음에 사용할 adjList를 선언했고, 마찬가지로 0~9까지 올 수 있다고 판단하여 10만큼의 공간을 할당했다.insertEdge
함수를 통해 만약 첫 숫자가 없을 경우 노드를 생성하여 해당 숫자를 인덱스로 가진 곳에 넣어주었다.- 첫 숫자의 공간에 노드가 존재할 경우 이를 따라 내려가도록 했다.
- flag를 도중에 만나면 멈추는 식으로 만들었다.
-
이렇게 하면 1개의 번호일 때 체클르 못해주어서 1개의 문자열이 들어올 때 flag를 심어주는 if문도 넣었다.
-
문자열 문제를 요즘 많이 풀면서 느낀 것은 다양한 자료구조를 통해 시각화를 할 수 있거나 반대 방향으로 탐색하면 조금 더 쉽게 문제를 접근할 수 있었다는 사실이다.
-
많이 부족했지만 그래도 끝까지 답을 안보고 스스로 코드를 작성해보는 계기가 되었고, 앞으로는 다양한 자료구조도 함께 생각해보는 사람이 되어야겠다.
python code
# 백준 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))
Author And Source
이 문제에 관하여(BAEKJOON #5052번 전화번호 목록 (문자열) - python), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@nathan29849/BAEKJOON-5052번-전화번호-목록-문자열-python저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)