일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- MAC
- Git
- django rest framework
- javascript
- HTML
- django ORM
- 알고리즘 연습
- 장고
- django widget
- Baekjoon
- 알고리즘 풀이
- 알고리즘
- c++
- AWS
- js
- Django
- es6
- 파이썬
- react
- DRF
- form
- CSS
- 알고리즘 문제
- 백준
- API
- PYTHON
- Algorithm
- web
- 파이썬 알고리즘
- java
- Today
- Total
수학과의 좌충우돌 프로그래밍
[Algorithm] Trie 자료구조 본문
KMP 알고리즘 에 이어서 문자열에서 검색에 위한 새로운 방법들을 알아보도록 하겠습니다. 이번에 알아볼 내용은 Trie 자료구조입니다.
Trie 자료구조
문자열 집합, {AB, ACD, ACEF, ACEG, HB, HC} 에 대해 Trie 자료구조가 어떻게 그려지는지 살펴보도록 합시다.
시작 부분이 같은 단어끼리 부모를 공유한다면, 다음과 같은 트리 모양을 얻을 수 있습니다. 이 트리에 대하여 탐색을 진행할 경우, 트리의 시간 복잡도는 O(H) (H 는 트리의 높이) 가 될 것입니다. 그리고 트리의 높이는 문자열 집합 중 가장 긴 문자열의 길이와 동일하기 때문에 Trie
자료구조를 사용하면 가장 긴 문자열의 길이를 M 이라 했을 때, O(M) 만에 문자열 검색이 가능합니다.
언제 사용해야 하지?
Trie
자료구조에 대해서 고려해야 할 부분은 단어의 길이
와children 의 수입니다.
단어의 길이는 시간복잡도에 직접적인 영향을 미치므로 단어의 길이가 너무 긴 문자열이 있을 경우 사용하기에 부적합 합니다. 또한 children 의 수 역시 탐색 시간에 많은 영향을 미칩니다. 알파벳의 경우, 최대 children 노드는 26개, 숫자의 경우 최대 children 노드는 10개가 되므로 이 정도의 수는 Trie 자료구조를 사용하는데 있어서 적당합니다.
C++ 로 구현
Trie
자료구조를 구현하기 위해서는 두 가지의 핵심적인 함수가 필요합니다. 새로운 문자열에 대해서 Trie
에 추가해주는 insert 함수와 구현된 자료구조에서 단어를 찾는 find 함수입니다.
기본적으로 알파벳 대문자 영단어에 대한 구현입니다.
insert 함수
void insert(const char* key) {
if (*key == '\0')
finish = true;
else {
int curr = *key - 'A';
if (next[curr] == NULL)
next[curr] = new Trie();
next[curr]->insert(key + 1);
}
}
재귀적으로 문자열 전체를 순회하면서 문자열 끝에 다다르면 끝내게 됩니다. 만약 트리가 만들어져 있지 않다면 새로운 Trie 객체를 만들어 길을 이어나가는 방식입니다.
find 함수
bool find(const char* key) {
if (*key == '\0')
return false;
if (finish)
return true;
int curr = *key - 'A';
return next[curr]->find(key + 1);
}
위에 insert 함수에서 문자열이 끝나는 지점에 finish를 true 로 해주었습니다. 따라서 문자열이 아직 끝나지 않았는데 finish가 true 라면 true 를 return 하고 이는 문자열 간의 포함관계가 있다는 소리입니다.
struct Trie {
bool finish;
Trie* next[26];
Trie() : finish(false) {
memset(next, 0, sizeof(next));
}
~Trie() {
for (int i = 0; i < 26; i++)
if (next[i])
delete next[i];
}
void insert(const char* key) {
if (*key == '\0')
finish = true;
else {
int curr = *key - 'A';
if (next[curr] == NULL)
next[curr] = new Trie();
next[curr]->insert(key + 1);
}
}
Trie* find(const char* key) {
if (*key == '\0')return this;
int curr = *key - 'A';
if (next[curr] == NULL)return NULL;
return next[curr]->find(key + 1);
}
};
Trie
자료구조에 대한 전체적인 코드입니다.
아래는 Trie 자료구조를 사용하는 백준 문제입니다.
'알고리즘 > 이론' 카테고리의 다른 글
[Algorithm] 그리디 알고리즘 (0) | 2019.09.14 |
---|---|
[Algorithm] 범위에 따른 이항계수 구하는 방법 (0) | 2019.09.11 |
[Algorithm] 범위에 따른 피보나치 수 구하는 방법 (0) | 2019.09.09 |
[Algorithm] 분할 정복을 이용한 a^b (0) | 2019.09.08 |
[Algorithm] KMP, Knuth-Morris-Pratt 알고리즘 (0) | 2019.08.21 |