JS Star 블로그

기억보다는 기록을✏️ 머신러닝, 웹개발, 물리학을 공부했고 계속 배워가고 있습니다.
📌 기존에 포스팅하던 블로그에서 포스트를 옮기는 중입니다.

[알고리즘BOOK] Trie구조

02 Sep 2020 » algorithm

Trie 구조

Trie 구조는 검색을 뜻하는 retrieval (검색)에서 딴 이름이다. 사실 발음할 때는 [트리]라고 해야 맞지만 tree 구조와 헷갈릴 수 있어 [트라이]라고 부른다고 한다. 의미처럼 검색을 위한 자료구조이다. 단어를 검색할 때 주로 사용되는 건 dictionary 구조인데, dict 구조는 한번의 검색으로 바로 찾을 수 있어 (O(1)) 시간 복잡도에 유리함을 가지고 있지만 공간 복잡도가 불리하다. Trie 구조는 dictionary의 공간 복잡도 문제까지 해결하면서 시간 복잡도도 적당히 좋다.

단어 carry, car, cat, dog, dust가 있다고 해보자. 이에 대한 trie 구조는 다음과 같이 만든다.

distribution

해당 문자가 나오지 않을 때까지 줄기를 타고 내려가면 된다. 그리고 해당 문자가 나오지 않으면 새로운 가지를 치면 된다. car와 carry을 보면 요소가 겹쳐있기 때문에 하나의 가지에 포함되어 있다. 하지만 위의 그림처럼 tree을 그리면 do라는 단어를 검색할 때, 단어가 있다고 판단할 수 있다. 그래서 단어가 끝났다는 것을 표시하는 마크가 필요하다.

distribution

알파벳 밑에 *가 True이면 그 알파벳이 단어의 끝이라는 뜻이다. 정리하면,

  1. 검색을 할 때 해당 단어가 있는지
  2. 단어의 맨 마지막 알파벳 아래에 *가 True 인지

이 두가지를 검사해야한다.

class Trie:
		def __init__(self):
    		self.head = {}

    # s는 들어갈 string
    def add(self, s):
        now = self.head
        for ss in s:
            if ss not in now:   # string에서 해당 알파벳이 없는 경우 dictionary를 추가
                now[ss] = {}
            now = now[ss]   # 최신화
        now['*'] = True

    def search(self, s):
        now = self.head
        for ss in s:
            if ss not in now:
                return False    # 단어 안에 있는 단어를 따라가다가 없는게 나오면 return False
            now = now[ss]
        if '*' in now:  # 경로에 있는 단어가 아닌 실제 있는 단어라면 return True
            return True
        else:
            return False    # 경로에 있는 단어인 경우 return False
> trie = Trie()
> trie.add("carry")
> trie.add("car")
> trie.add("dog")
> trie.search("carry")
True
> trie.search("car")
True
> trie.search("care")
False
> trie.head
{'c': {'a': {'r': {'*': True, 'r': {'y': {'*': True}}}}},
 'd': {'o': {'g': {'*': True}}}}