|S|
는 문자열 S
의 길이를 의미함문자열 집합이 다음과 같다고 해보자
"cat", "car", "dog"
이 문자열 집합을 트라이에 저장하면 아래와 같다
"cat"
을 삽입하면 c -> a -> t
노드 생성"car"
은 c -> a
까지는 이미 존재하므로 그 노드를 재사용하고, r
만 추가"dog"
는 완전히 새로운 경로 d -> o -> g
로 생성L
일 때 검색은 O(L)"ca"
로 시작하는 모든 단어 찾기 가능operations
: 삽입(insert), 삭제(erase), 탐색(find)
const int ROOT = 1; // 루트 노드는 항상 1번
int unused = 2; // 노드 번호를 카운팅하는 숫자
const int MX = 10000 * 500 + 5; // 최대 등장 가능한 문자의 수
bool chk[MX}; // 리프 노드인지 체크
int nxt[MX][26]; // 트리
for(int i=0; i<MX; i++)
fill(nxt[i], nxt[i]+26, -1); // 초반에 트리는 -1로 초기화
void insert(string& s){
int cur = ROOT;
for(char c : s) {
int idx = c - 'a';
if(nxt[cur][idx] == -1)
nxt[cur][idx] = unused++;
cur = nxt[cur][idx];
}
chk[cur] = true;
}
bool find(string& s){
int cur = ROOT;
for(char c : s) {
int idx = c - 'a';
if(nxt[cur][idx] == -1)
return false;
cur = nxt[cur][idx];
}
return chk[cur];
}
void erase(string& s){
int cur = ROOT;
for(char c : s) {
int idx = c - 'a';
if(nxt[cur][idx] == -1)
return;
cur = nxt[cur][idx];
}
chk[cur] = false;
}
문자열에 대한 접미어 트라이가 있다면 다음을 쉽게 찾을 수 있다.
S
의 모든 접미어를 트라이에 삽입P
가 트라이에 존재하면, 이는 S
의 부분 문자열임문자열 S = "abac"
의 접미어:
abac, bac, ac, c
트라이에 이 접미어들을 넣고 "bac"
와 "aca"
가 있는지 검사해보자.
단순히 한 문자씩 루트에서 대응되는 간선을 따라가면 된다
"bac"
-> (O)"aca"
-> (X)"abac"와 "ac"의 최장 공통 접두어를 찾아보자
트라이의 DFS를 이용하면 정렬 없이 사전순 순회 가능