어떤 문제를 푸는가
문자열의 집합을 글자 단위로 가지를 뻗는 트리 에 저장해, "이 문자열이
집합에 있는가", "이 접두사로 시작하는 단어가 있는가" 같은 질의를 문자열
길이에 비례하는 시간 에 답합니다. 자동 완성, 사전, 접두사 카운팅의 토대입니다.
구조 — 글자를 따라 내려가는 길
루트에서 시작해 한 글자씩 자식으로 내려가며 문자열을 따라갑니다. 공통 접두사를
가진 단어들은 트리의 앞부분 경로를 공유 합니다.
"cat", "car", "card", "dog" 를 담은 트라이
(root)
├─ c ─ a ─ t (끝)
│ └ r (끝) ─ d (끝)
└─ d ─ o ─ g (끝)
각 노드는 자식 포인터들(보통 알파벳 개수만큼의 배열 또는 맵)과 "여기서 단어가
끝나는가"를 나타내는 표시를 가집니다. card는 car의 경로를 그대로 지나
d로 한 칸 더 갑니다.
핵심 연산
| 연산 | 방법 | 시간 |
|---|---|---|
| 삽입 | 글자를 따라 내려가며 없는 자식은 새로 만들고, 끝에 종료 표시 | \(O(L)\) |
| 탐색 | 글자를 따라 내려가다 막히면 없음, 끝에서 종료 표시 확인 | \(O(L)\) |
| 접두사 존재 | 글자를 따라 내려갈 수만 있으면 됨(종료 표시 무관) | \(O(L)\) |
\(L\)은 문자열 길이. 삽입·탐색 비용이 트리에 담긴 단어 수와 무관 하다는 점이
해시/정렬과 다른 강점입니다.
해시·정렬과의 비교
- 해시 집합 — 평균 \(O(L)\)로 존재 판정은 빠르지만, "접두사로 시작하는
단어가 있나" 같은 질의는 어렵습니다. - 정렬 + 이분 탐색 — 접두사 질의는 가능하나 동적 삽입이 불편합니다.
- 트라이 — 접두사 관련 질의에 자연스럽고, 동적 삽입/삭제도 쉽습니다.
복잡도와 공간
- 시간: 각 연산 \(O(L)\).
- 공간: 노드 수 × 알파벳 크기. 자식을 배열 로 두면 빠르지만 메모리가 크고,
맵/해시 로 두면 메모리는 절약되나 상수가 큽니다.
전체 문자열 길이 합이 \(S\)면 노드 수는 \(O(S)\) 이하입니다(공통 접두사는 공유).
다음 강의에서 구현과 응용을 봅니다.