전화번호 목록이 주어진다. 이때, 이 목록이 일관성이 있는지 없는지를 구하는 프로그램을 작성하시오.
전화번호 목록이 일관성을 유지하려면, 한 번호가 다른 번호의 접두어인 경우가 없어야 한다.
예를 들어, 전화번호 목록이 아래와 같은 경우를 생각해보자
이 경우에 선영이에게 전화를 걸 수 있는 방법이 없다. 전화기를 들고 선영이 번호의 처음 세 자리를 누르는 순간 바로 긴급전화가 걸리기 때문이다. 따라서, 이 목록은 일관성이 없는 목록이다.
첫째 줄에 테스트 케이스의 개수 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
문자열을 서로 비교하여 둘 중 하나의 문자열이 다른 하나의 문자열의 앞부분의 일부인가를 확인하는 문제입니다.
모든 문자열을 서로 비교하여 문제를 해결할 수도 있지만, 그렇게 되면 너무 많은 시간이 필요합니다.
따라서, 문자열을 효율적인 시간 내에 탐색할 수 있는 트라이를 사용하면 빠른 시간내에 문제를 해결할 수 있습니다!
import sys
input = sys.stdin.readline
class Node(object): #트라이의 노드 클래스
def __init__(self, key, data=None):
self.key = key
self.data = data
self.children = {}
class Trie(object): #트라이 클래스
def __init__(self):
self.head = Node(None)
#문자열 삽입 함수로, 트라이의 어느 문자열이 string의 접두사면 False, 아니라면 True return
def insert(self, string):
current = self.head
for char in string:
if char not in current.children:
current.children[char] = Node(char)
else:
#삽입하려는 문자열의 접두사가 존재하면 False return
if current.children[char].data: return False
current = current.children[char]
current.data = string
return True #접두사 존재하지 않으면 True return
t = int(input())
for _ in range(t):
n = int(input())
trie_tree = Trie() #트라이 생성
#입력받은 전화번호 리스트를 길이 순으로 정렬
phone_nums = sorted([input().strip() for __ in range(n)], key=lambda x: len(x))
is_consist = True #접두사 존재 여부 저장 변수
for num in phone_nums:
if not trie_tree.insert(num): #접두사가 존재하는 경우(False가 return된 경우)
is_consist = False
break
print("YES" if is_consist else "NO")
트라이를 클래스로 구현하여 문제를 해결하였습니다.
대신, 문자열을 트라이에 추가하는 과정에서 한 번호가 다른 번호의 접두사인지를 확인할 수 있기 때문에 insert 함수만으로도 충분합니다.
그래서 저는 find 함수는 구현하지 않았습니다😏
insert함수에서, 문자열 string을 추가하는 과정에서 string의 substring이 이미 트라이에 존재하는지 여부를 확인합니다. 추가하는 도중 노드의 data의 값이 존재한다면, 바로 그 data의 값이 string의 접두사가 됩니다.
📌이 때 반드시 고려해야 하는 점이 있습니다.
접두사의 길이는 문자열의 길이보다 짧아야 합니다.
즉, 추가하려는 문자열의 접두사를 트라이에서 찾기 위해서는 추가하려는 문자열의 길이보다 짧은 모든 문자열들이 트라이에 미리 추가되어 있어야 한다는 뜻입니다.
따라서, 문자열들을 insert할 때, 문자열의 길이 순으로 정렬하는 과정이 반드시 선행되어야 합니다.