상상쓰

[프로그래머스] 가사 검색 본문

Coding Test

[프로그래머스] 가사 검색

상상쓰 2021. 7. 22. 10:05

https://programmers.co.kr/learn/courses/30/lessons/60060

 

코딩테스트 연습 - 가사 검색

 

programmers.co.kr

 

저번에 풀었던 [3차] 자동완성에서 썼던 Trie 자료구조를 이용하였다.

 

'?' 가 접두사 아니면 접미사로만 존재하기 때문에 두 개의 dictionary 를 만들어 검색할 수 있도록 하였다.

예를 들어, 'frodo' 를 dictionary에 추가시키면 

{'f': {'*': [5], 'r': {'*': [5], 'o': {'*': [5], 'd': {'*': [5], 'o': {'*': [5]}}}}}} 이고 '*' 는 그 위치의 문자를 가진 문자열의 길이가 5인 것이 하나 존재한다는 의미이다.

 

'front', 'frost' 과 'fronzen'를 추가시키면, 

{'f': {'*': [5, 5, 5, 6], 'r': {'*': [5, 5, 5, 6], 'o': {'*': [5, 5, 5, 6], 'd': {'*': [5], 'o': {'*': [5]}}, 'n': {'*': [5], 't': {'*': [5]}}, 's': {'*': [5], 't': {'*': [5]}}, 'z': {'*': [6], 'e': {'*': [6], 'n': {'*': [6]}}}}}}} 로

'f' 로 시작하는 문자열은 길이가 5인 것이 세 개, 6인 것이 한 개 존재한다는 것이고, 'f' -> 'r' -> 'o' -> 'z' 에서 '*' 의 값이 [6] 이기 때문에 접두사가 'froz' 로 해당하는 문자열은 길이가 6인 것이 한 개 존재한다는 것이다.

 

즉, 완성한 dictionary 를 통해 'fro??' 와 일치하는 문자열을 찾을 때는 '?' 가 나오기 전에 'f' -> 'r' -> 'o' 에서의 '*' 에 해당하는 배열의 원소 중에서 'fro??' 의 길이인 5의 개수를 구하면 된다. 

 

class Trie:
    dictionary = {}
    dictionaryReverse = {}
    length = []
    
    def insert(self, string):
        current_dic = self.dictionary
        current_dicReverse = self.dictionaryReverse
        N = len(string)        
        self.length.append(N)
        
        for i in range(N):
            C = string[i]
            R = string[N-1-i]
            
            if C not in current_dic:
                current_dic[C] = {'*' : [N]}
            else:
                current_dic[C]['*'].append(N)
            
            current_dic = current_dic[C]
            
            if R not in current_dicReverse:
                current_dicReverse[R] = {'*' : [N]}
            else:
                current_dicReverse[R]['*'].append(N)
            
            current_dicReverse = current_dicReverse[R]

    def search(self, string):
        current_dic = self.dictionary if string[0] != '?' else self.dictionaryReverse
        string = string if string[0] != '?' else string[::-1]
        N = len(string)
        
        if string[0] == '?':
            return self.length.count(N)
        else:
            for i in string:
                if i in current_dic:
                    current_dic = current_dic[i]
                else:
                    if i != '?':
                        return 0
                    else:
                        return current_dic['*'].count(N)
        
def solution(words, queries):
    answer = []
    T = Trie()
    
    for i in words:
        T.insert(i)
    
    for i in queries:
        answer.append(T.search(i))

    return answer

print(solution(['frodo', 'front', 'frost', 'frozen', 'frame', 'kakao'], ['fro??', '????o', 'fr???', 'fro???', 'pro?'])) # [3, 2, 4, 1, 0]

'Coding Test' 카테고리의 다른 글

[프로그래머스] 튜플  (0) 2021.07.23
[백준] 소수 최소 공배수  (0) 2021.07.22
[프로그래머스] 오픈채팅방  (0) 2021.07.21
[백준] 최고의 피자  (0) 2021.07.20
[프로그래머스] 전화번호 목록  (0) 2021.07.19
Comments