콘텐츠로 바로가기

Tries & Suffix Trees

문자열의 접두사와 접미사를 트리 형태로 구조화하여 검색과 패턴 매칭의 물리적 효율을 극대화하는 텍스트 인덱싱 기술을 다루는 학습 노드입니다.

Article
M

Me

hyunyoun's Blog

data-structures-algorithmsdata-structuresalgorithmscore-data-structurestriessuffix-treesadvanced-data-structureslearning9 min read

1. Overview

트라이와 접미사 트리(Tries & Suffix Trees)는 문자열(String) 집합에 대한 탐색, 접두사(Prefix) 자동완성, 패턴 매칭을 O(m) 시간(m=검색 문자열 길이)으로 수행하는, 문자를 트리 엣지(Edge)로 인코딩한 극한의 문자열 인덱스 공학입니다.

학습자는 사전(Dictionary)에 있는 10만 개의 단어 중 "app"으로 시작하는 모든 단어를 찾을 때, 해시 테이블이 O(n)의 전수 탐색을 요구하는 반면 트라이(Trie)가 O(m)(m="app"의 길이=3)에 찾아내는 접두사 압축 역학을 뜯어봅니다. 나아가 텍스트 전체를 전처리하여 임의의 부분 문자열을 O(m)에 찾는 **접미사 트리(Suffix Tree)와 접미사 배열(Suffix Array)**의 정보 압축 기하학을 해부하여, 검색 엔진 자동완성, DNA 시퀀스 분석, 안티바이러스 패턴 매칭 엔진의 내부를 통달하는 역량을 확보합니다.

2. Scope & Boundaries

In-Scope

  • 트라이 (Trie / Prefix Tree): 노드 구조(children[26], is_end), 삽입/탐색/삭제 O(m), 접두사 검색, 공통 접두사 길이(LCP).
  • 압축 트라이 (Compressed Trie / Radix Tree / Patricia Tree): 단일 자식 노드 체인 압축, 라우팅 테이블(IP Routing Table) 최장 접두사 매칭(LPM).
  • 접미사 자료구조 (Suffix Structures): 접미사 배열(Suffix Array, SA), LCP 배열(Longest Common Prefix), Ukkonen's O(n) 접미사 트리 구축.
  • 실무 응용 (Real-world Applications): 자동완성(Autocomplete), 철자 교정(Spell Checker), 침입 탐지 시스템(IDS) 다중 패턴 매칭(Aho-Corasick).

Out-of-Scope

  • KMP, Rabin-Karp 문자열 매칭: 단일 패턴 매칭 알고리즘 \rightarrow 04-04-02. String Matching & Automata 영역.
  • B-트리 기반 문자열 인덱스: 데이터베이스의 Like 쿼리 최적화 \rightarrow 06-01. Database Index Internals 영역.

Boundaries

  • Trie vs. Hash Map for String Search: 해시맵은 단어 전체가 정확히 일치하는 경우(Exact Match)에 O(1)이지만 접두사 검색은 불가능합니다. 트라이는 접두사 검색 O(m)이 완벽하지만, 노드마다 자식 배열(children[26])을 유지해야 하므로 알파벳이 큰 경우(예: 한글, 유니코드) 메모리 사용량이 폭발하는 대가를 치릅니다.

3. Counterexample

  • 일반 Trie의 메모리 폭발 (Trie Memory Explosion): 알파벳이 256가지(ASCII 전체)인 경우, 각 노드가 children[256] 배열을 가지므로 빈 자식 포인터만으로 노드 1개당 256 * 8Byte = 2KB를 차지합니다. 단어 10만 개를 삽입하면 노드가 수백만 개 생기며 수 기가바이트 메모리를 소비할 수 있습니다. 영어 소문자(26가지)에 최적화된 트라이를 유니코드 범용 문자열에 무비판적으로 적용하는 실수입니다. 해시맵(children = {})을 자식 저장소로 쓰거나 압축 트라이를 써서 해결해야 합니다.
  • 접미사 트리 Naive O(n²) 구축의 함정 (Naive Suffix Tree Construction): 길이 n=100만인 DNA 서열에 대해, 모든 n개의 접미사를 하나씩 트라이에 삽입하는 Naive 방법으로 접미사 트리를 만들려는 시도. 삽입 1회가 O(n)이므로 전체 O(n²) = 10^12 연산으로 수천 초가 걸립니다. Ukkonen's 알고리즘(O(n) 선형 시간 접미사 트리 구축)을 사용해야 하지만 구현 난이도가 극도로 높습니다.

4. Prerequisites

  • 재귀와 트리 (Basic): 트라이는 트리 자료구조이므로 재귀 탐색의 기초가 필요합니다. (04-02-01 Binary Trees, 04-03-01 Recursion)
  • 해시맵 (Recommended): 압축 트라이에서 children을 해시맵으로 구현하는 패턴을 이해하기 위해 필요합니다. (04-02-03 Hash Tables)

5. Learning Map

Sequence Core Cluster Objective & Description Evidence (BoK)
1 Trie Fundamentals 문자 하나가 엣지, 단어 끝이 is_end 플래그인 트라이 구조와, 접두사 탐색 O(m)의 기하학을 쥡니다. P1
2 Compressed Trie (Radix Tree) 단일 자식 노드 체인을 통째로 압축(엣지에 문자열 저장)하여 메모리를 절약하는 압축 트라이를 해부합니다. P5
3 Suffix Array & LCP 텍스트의 모든 접미사를 정렬해 배열에 저장하고 LCP로 공통 부분을 찾는 접미사 배열의 역학을 뜯어봅니다. Industry
4 Aho-Corasick Multi-Pattern 트라이에 실패 함수(Failure Links)를 박아 K개 패턴을 텍스트 한 번 스캔으로 동시 탐색하는 마법을 장악합니다. Industry

6. Learning Topics

Basic

Core Topic 01: 문자 경로와 단어의 지도, 트라이 기초 (Trie Fundamentals)

  • Why to Learn: 검색창에 "app"을 치는 순간 "apple", "application", "appreciate" 등이 즉각 드롭다운되는 자동완성 기능이, 10만 개의 단어를 O(3) 시간에 탐색하는 트라이의 접두사 압축 마법임을 꿰기 위함입니다.
  • What to Learn:
    • Concepts: TrieNode(children[26], is_end), 삽입(Insert), 탐색(Search), 접두사 탐색(StartsWith).
    • Skills: DFS로 모든 단어 열거, 삭제(Delete, 역방향 DFS로 후손 없는 노드 제거).
    • Tools: Python defaultdict(dict) 기반 트라이 구현.
  • How to Learn:
    • 1단계: "apple"과 "app" 삽입. 노드 경로: root → a → p → p → is_end=True(app) → l → e → is_end=True(apple). "app" 탐색 시 root→a→p→p까지 이동, is_end=True 확인 → 존재. "application" 탐색 시 root→a→p→p→l →(없음) → 탐색 실패 역학을 해부합니다.
    • 2단계: 접두사 탐색 startsWith("ap"): root→a→p까지 이동 성공하면 "ap"로 시작하는 단어가 있음을 반환. 이후 DFS로 하위 모든 단어(is_end=True 경로 목록)를 수집하는 자동완성 구현을 뜯어봅니다.
  • Implement: 파이썬 Trie 클래스. TrieNode(children=defaultdict(TrieNode), is_end=False). insert(word), search(word), starts_with(prefix), autocomplete(prefix) 구현. ["apple","app","application","apply"] 삽입 후 autocomplete("app")["app","apple","application","apply"] 검증.

Core Topic 02: 체인 압축과 최장 접두사, 압축 트라이 (Radix Tree & IP Routing)

  • Why to Learn: 인터넷 라우터가 수백만 개의 IP 주소 접두사(192.168.1.0/24) 중 패킷의 목적지와 가장 긴 접두사가 일치하는 다음 홉(Next Hop)을 O(m) 시간에 찾는 **최장 접두사 매칭(LPM, Longest Prefix Match)**이 압축 트라이(Radix Tree) 기반임을 장악하기 위해서입니다.
  • What to Learn:
    • Concepts: 압축 트라이(Radix Tree / Patricia Tree), 엣지에 문자열 저장, 최장 접두사 매칭(LPM).
    • Skills: 공통 접두사(LCP) 계산, 노드 분할(Split) 연산.
    • Tools: Linux 커널 lib/radix-tree.c.
  • How to Learn:
    • 1단계: 일반 트라이에서 "application"을 삽입하면 11개의 노드가 생기는 반면, 압축 트라이(Radix)에서는 "applica"가 하나의 엣지 라벨이 되어 단 몇 개의 노드로 표현됩니다. 새 단어 "apple"이 들어오면 공통 접두사 "appl"에서 노드를 분할(Split)하는 역학을 해부합니다.
    • 2단계: IP 라우팅에서 목적지 192.168.1.100에 대해 라우팅 테이블 [192.168.1.0/24, 192.168.0.0/16, 192.0.0.0/8] 중 가장 긴 접두사 192.168.1.0/24를 Radix Tree를 통해 O(32)(IP 비트 수)에 찾는 LPM 역학을 뜯어봅니다.
  • Implement: 파이썬 RadixTree 클래스(단순화). insert(word) 시 기존 노드와 공통 접두사 LCP 계산 후 분할. search(word) O(m) 구현. ["test","testing","tester","slow","slowly"] 삽입 후 "testing" 탐색, "test" 접두사 모든 단어 열거 검증.

Practical

Core Topic 03: 모든 접미사의 거울, 접미사 배열과 LCP (Suffix Array & LCP)

  • Why to Learn: 게놈 서열 분석("ATCG" 패턴 반복 탐색), 표절 검사(최장 공통 부분 문자열), 데이터 압축(LZ77, Bzip2)의 핵심 엔진인 접미사 배열을 O(n log n) 이내로 구축하는 역학을 꿰기 위함입니다.
  • What to Learn:
    • Concepts: 접미사 배열(Suffix Array, SA), 접미사(Suffix), SA 정렬 O(n log²n) Naive / O(n log n) Prefix Doubling.
    • Skills: LCP 배열(Kasai's Algorithm, O(n)), SA+LCP로 최장 반복 부분 문자열 탐색.
    • Tools: Python sorted([(s[i:],i) for i in range(n)]) Naive SA 구축.
  • How to Learn:
    • 1단계: 문자열 "banana"의 모든 접미사 ["banana","anana","nana","ana","na","a"]를 사전순 정렬 → ["a","ana","anana","banana","na","nana"]. SA = [5,3,1,0,4,2] (정렬된 접미사의 시작 인덱스). "ana"가 텍스트에 등장하는 위치를 SA 이진 탐색으로 O(m log n)에 찾는 역학을 해부합니다.
    • 2단계: LCP 배열: 연속된 두 정렬 접미사의 공통 접두사 길이. LCP[2]=3 (anana와 banana의 LCP=0... "a"와 "ana"의 LCP=1). Kasai's Algorithm으로 O(n) LCP 배열 구축 역학을 뜯어봅니다.
  • Implement: 파이썬 build_suffix_array(s). Naive: sorted(range(len(s)), key=lambda i: s[i:]). 문자열 "mississippi"의 SA를 구축하고, 이를 이용해 패턴 "issi" 등장 위치를 bisect(이진 탐색)로 O(m log n)에 탐색하는 검색 엔진 구현.

Advanced

Core Topic 04: 실패에서 배우는 다중 패턴 탐색, Aho-Corasick 알고리즘 (Aho-Corasick)

  • Why to Learn: 안티바이러스 소프트웨어가 10만 개의 악성코드 패턴을 텍스트 1번 스캔으로 동시에 탐색하거나, 네트워크 침입 탐지 시스템(IDS/IPS)이 실시간 패킷 페이로드에서 수천 개의 악성 시그니처를 동시에 찾는 핵심 알고리즘을 장악하기 위해서입니다.
  • What to Learn:
    • Concepts: Aho-Corasick 오토마톤, 트라이 + 실패 링크(Failure Links) + 출력 링크(Output Links), BFS로 실패 링크 구축, O(n+m+z) 탐색(n=텍스트, m=패턴 합계, z=매칭 수).
    • Skills: 실패 링크를 KMP의 실패 함수(Failure Function)와 연결하여 이해.
    • Tools: Aho-Corasick 라이브러리(pyahocorasick).
  • How to Learn:
    • 1단계: 패턴 ["he","she","his","hers"]를 트라이에 삽입. BFS로 실패 링크 구축: 탐색이 실패할 때 "현재 접두사의 가장 긴 적절한 접미사이면서 트라이에 있는 노드"로 점프하는 KMP-like 실패 회복 역학을 해부합니다.
    • 2단계: 텍스트 "ahishers"를 단 한 번 선형 스캔하며 패턴 ["his", "she", "hers"] 3개가 각각 텍스트 어디서 등장하는지 동시에 찾아내는 O(n+m+z) 시간 복잡도 증명을 뜯어봅니다.
  • Implement: 파이썬 AhoCorasick 클래스. insert(patterns)build_failure_links() (BFS). search(text)"ushers" 텍스트에서 ["he","she","his","hers","ush"] 패턴 매칭 결과 [(2,"he"),(1,"she"),(3,"hers")] 등 위치+패턴 쌍 출력. 패턴 5개를 각각 개별 탐색하는 O(5n) vs Aho-Corasick O(n+m+z) 속도 비교.

7. Terminology

Term (EN / ko, abbr) 1문장 정의 단계(기본/권장/실무/심화) 역할/맥락 관련 개념 유사/대비/함께 사용 오해 포인트 Evidence(Primary/Secondary/Industry) Flags(core)
Trie 문자열의 접두사를 공유하여 계층적으로 저장하는 문자 전이 기반 트리입니다. 기본 텍스트 인덱싱 Prefix / Stem Hash Map '이진 트리'와는 분기 방식이 다름 P1:CS2023 core
Radix Tree 자식이 하나인 노드들을 병합하여 전이 단계를 줄인 압축된 트라이 구조입니다. 추천 공간 절약 Compression Patricia 단순 트라이보다 구현 복잡함 Industry Kernel core
Suffix Tree 문자열의 모든 접미사를 트라이로 구성하여 부분 문자열 검색을 가속하는 자료구조입니다. 추천 고속 검색 Pattern / Match Suffix Array 메모리 점유가 매우 큼 P1:CS2023 core
Suffix Array 모든 접미사를 사전순 정렬한 인덱스 배열로, 트리 대비 메모리 효율이 극강인 문자열 색인입니다. 실무 대규모 색인 LCP / BWT Suffix Tree 검색 시 이진 탐색 필요함 Industry core

8. References

Primary

Secondary

  • [Algorithms on Strings, Trees and Sequences] Dan Gusfield — The suffix tree bible.
  • [Advanced Data Structures] Peter Brass — Advanced trie variants.

Industry

  • [Cloudflare: Use of Radix Trees for IP Routing] — Networking case study.
  • [Google: Auto-complete Architecture with Tries] — Real-world application.

9. Final Checklist

Primary

  • '트라이' 자료구조에서 특정 단어의 존재 여부를 확인할 때의 시간 복잡도가 왜 '데이터 개수'가 아닌 '단어 길이'에 의존하는지 설명 가능한가? (P1)
  • '접미사 트리'를 이용해 문서 내에서 특정 패턴을 찾는 무궁무진한 과정의 물리적 복잡도를 입증할 수 있는 가? (P1)

Secondary

  • 압축되지 않은 트라이가 왜 실무 대규모 데이터셋에서 '메모리 단편화'와 '공간 낭비'를 유발하는지 물리적 근거로 소통 가능한가?
  • 접미사 트리와 접미사 배열 중, 메모리가 극도로 제한된 임베디드 환경에서 어느 것을 선택할지 수리적 트레이드-오프를 도출할 수 있는 가?

Industry

  • 검색 엔진의 '검색어 추천' 기능을 설계할 때, 사용자 로그를 트라이에 동적으로 반영하는 물리적 갱신 시나리오를 제안할 수 있는 가? (SFIA)
  • 유전체 서열 분석(Alignment) 시, 수조 개의 염기서열 속에서 특정 유전자를 빛의 속도로 찾는 BWT 인덱스의 물리적 기여도를 기술할 수 있는 가?

Advanced Data Structures & Algorithms

3 / 4