다음과 같은 문자열 집합이 있습니다.
S = {"HE", "HELLO", "WORLD", "SHE"}
위 문자열 집합에 "SHE"라는 문자열이 포함되어 있는지 확인하고 싶다면 어떻게해야 할까요? 🤔
Naive한 방법으로는 이중 반복문으로 일일이 비교하는 방법이 있습니다. 문자열 집합의 갯수를 N, 문자열의 최대길이를 M이라고 했을 때, 이 방법의 시간 복잡도는 O(NM)입니다.
Trie는 문자열 집합에서 특정 문자열이 존재하는지 찾을 때 O(M)의 시간 복잡도로 해결할 수 있습니다.
Trie는 문자열을 트리의 형태로 자료구조화하는 자료구조입니다. 위 문자열 집합을 Trie로 표현하면 다음과 같습니다.
이해가 되시나요?
위 트리에서 빨간색 테두리로 된 노드는 문자열의 마지막 지점을 의미합니다.
이것이 필요한 이유는 "HE", "HELLO" 와 같이 앞의 문자가 중복되는 문자열을 위해서인데요, 문자열 집합에서 "HE"라는 문자열이 있는지 확인해야한다고 해보겠습니다. 그럼 탐색 과정은 다음과 같습니다.
public class TrieTest {
public static void main(String[] args) {
String[] strArr = {"HE", "HELLO", "WORLD", "SHE"};
Trie trie = new Trie();
for (String str : strArr) {
trie.insert(trie.root, str, 0);
}
System.out.println(trie.contains(trie.root, "HELLO", 0));
}
private static class Trie {
private Node root = new Node();
public void insert(Node head, String str, int idx) {
int charIdx = str.charAt(idx) - 65;
if (head.child[charIdx] == null) {
head.child[charIdx] = new Node();
}
if (idx == str.length() - 1) {
head.child[charIdx].finish = true;
} else {
insert(head.child[charIdx], str, idx + 1);
}
}
public boolean contains(Node head, String str, int idx) {
int charIdx = str.charAt(idx) - 65;
if (head.child[charIdx] == null) {
return false;
}
if (idx == str.length() - 1) {
return head.child[charIdx].finish;
}
return contains(head.child[charIdx], str, idx + 1);
}
private static class Node {
Node[] child = new Node[26];
boolean finish = false;
}
}
}