트라이 (Trie)
Updated:
트라이 이해
트라이(Trie)는 문자열 집합을 표현하는 아래 그림과 같은 자료구조이다.
기본적으로 K진 트리구조를 이루고 있으며 문자열의 prefix를 빠르게 찾을 수 있다.
그러나 많은 공간이 필요하다는 단점이 존재한다. 예를들어 알파벳의 경우 총 26자리의 배열을 각 노드마다 확보해야 한다.
따라서 공간 복잡도는 O(포인터 크기 * 포인터 배열 개수 * 트라이 노드 개수)가 된다.
트라이 구현
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int ALPHABETS = 26;
int toNumber(char ch) { return ch-'A'; }
// 트라이의 한 노드를 나타내는 객체
struct TrieNode {
TrieNode* children[ALPHABETS];
// 이 노드가 종료 노드인가?
bool terminal;
TrieNode() : terminal(false) {
memset(children,0,sizeof(children));
}
~TrieNode() {
for(int i=0;i<ALPHABETS;i++)
if(children[i]) delete children[i];
}
// 이 노드를 루트로 하는 트라이에 문자열 key를 추가한다.
void insert(const char* key) {
// 문자열이 끝나면 terminal만 참으로 바꾸고 종료
if(*key==0) terminal=true;
else {
int next=toNumber(*key);
// 해당 자식 노드가 없다면 생성한다.
if(children[next]==NULL) children[next]=new TrieNode();
// 해당 자식 노드로 재귀호출
children[next]->insert(key+1);
}
}
// 이 노드를 루트로 하는 트라이에 문자열 key와 대응되는 노드를 찾는다.
// 없으면 NULL을 반환
TrieNode* find(const char* key) {
if(*key==0) return this;
int next=toNumber(*key);
if(children[next]==NULL) return NULL;
return children[next]->find(key+1);
}
};
트라이 성능
$N$개의 원소가 들어있는 문자열 집합에서 길이 $M$인 접두사(prefix)를 찾기위한 시간 복잡도는 $O(M)$을 가진다. 그러나 메모리가 너무 많이 필요하기 때문에 대회에 출제된다면 문자열의 개수가 적은 경우가 나온다.
Comments