파이썬으로 부시자! Python with Coreenee

프로그래머스 - 가사검색- Trie자료구조

문제

스크린샷 2020-09-09 오전 12 21 06 스크린샷 2020-09-09 오전 12 21 26

입력

스크린샷 2020-09-09 오전 12 21 35


나의 처음 코드

처음에는 startswith, endswith의 기능을 사용하였지만 효율성 2번이 통과하지 못해 실패했다. 또한 딕셔너리를 이용하여 푸는 풀이도 효율성이 실패했다. 다음으로 Trie 자료구조를 사용하였다. 이진트리와는 다르게 자식들이 여럿 있을 수 있으므로, 부모가 자식을 저장하는 자료구조를 잘 설계하는 것이 중요하다. 또한, 리프노드에서 일치하는 단어를 찾으면 시간초과가 날 수 있으므로, 각 노드별로 가지고 있는 자식들의 길이 종류? (자식들을 길이별로 갯수를 체크한) 자료구조를 사용하면, 리프노드까지 안 가도 빠르게 셀 수 있다.


풀이 사진

개발-134

class Node:
    def __init__(self, char):
        self.char = char
        self.data = None
        self.children = {}
        self.length = {}

def insert(word, head):
    curNode = head
    w_len = len(word)
    for w in word:
        if w in curNode.children:
            curNode = curNode.children[w]
        else:
            newNode = Node(w)
            curNode.children[w] = newNode
            curNode = curNode.children[w]
        if w_len in curNode.length:
            curNode.length[w_len] += 1
        else:
            curNode.length[w_len] = 1
    curNode.data = word


def solution(words, queries):
    answer = []
    head = Node('')
    bhead = Node('')
    cnt_dict = {}
    for word in words:
        insert(word, head)
        insert(word[::-1], bhead)
        if len(word) in cnt_dict:
            cnt_dict[len(word)] += 1
        else:
            cnt_dict[len(word)] = 1

    for query in queries:
        if query[0] == '?' and query[-1] == '?':  # ??????일떄
            try:
                answer.append(cnt_dict[len(query)])
            except:
                answer.append(0)
        else:
            org_len = len(query)
            if query[0] == '?':
                query = query[::-1]
                cur = bhead
            else:
                cur = head
            query = query.split("?")[0]
            idx = 0
            flag = 0
            for char in query:
                if char in cur.children:
                    cur = cur.children[char]
                else:
                    flag = 1
                    break
            if flag:
                answer.append(0)
            else:
                try:
                    answer.append(cur.length[org_len])
                except:
                    answer.append(0)

    return answer