Live Today

[자료ꡬ쑰] Trie(트라이) 본문

Computer Science/자료ꡬ쑰

[자료ꡬ쑰] Trie(트라이)

ilivetoday 2022. 10. 3. 21:32
λ°˜μ‘ν˜•

πŸ“‹ λͺ©μ°¨

  • Trie μžλ£Œκ΅¬μ‘°λž€?
  • Trie μž₯/단점
  • Trie μ½”λ“œ κ΅¬ν˜„
  • Trie κ΄€λ ¨ μ•Œκ³ λ¦¬μ¦˜ 문제

 

1️⃣ Trie μžλ£Œκ΅¬μ‘°λž€?

  • λ¬Έμžμ—΄μ— νŠΉν™”λœ 자료 ꡬ쑰인 트라이(Trie)λŠ” λ¬Έμžμ—΄ 집합을 ν‘œν˜„ν•˜λŠ” 트리 μžλ£Œκ΅¬μ‘°μ΄λ‹€.
  • μš°λ¦¬κ°€ μ›ν•˜λŠ” μ›μ†Œλ₯Ό μ°ΎλŠ” μž‘μ—…μ„ O(n)에 ν•΄κ²° ν•  수 μžˆλŠ” μžλ£Œκ΅¬μ‘°μ΄λ‹€. μ—¬κΈ°μ„œ n은 λ¬Έμžμ—΄μ˜ κΈΈμ΄μž…λ‹ˆλ‹€.
  • 루트 λ…Έλ“œκ°€ λ˜λŠ” κ°€μž₯ μ΅œμƒμœ„ λ…Έλ“œμ—λŠ” μ–΄λ– ν•œ 단어도 듀어가지 μ•Šκ³ , 루트 μ•„λž˜ λ…Έλ“œλΆ€ν„° λ¬Έμžμ—΄λ“€μ˜ 접두사가 ν•˜λ‚˜μ”© λ‚˜νƒ€λ‚˜κ²Œ λœλ‹€.

πŸ’‘μš°λ¦¬κ°€ μ‚¬μ „μ—μ„œ 단어λ₯Ό 찾을 λ•Œμ™€ λΉ„μŠ·ν•œ λ©”μ»€λ‹ˆμ¦˜μž…λ‹ˆλ‹€. ν•œ κΈ€μžμ”© μ°Ύμ•„κ°€λ©° λ¬Έμžμ—΄μ— λ„λ‹¬ν•©λ‹ˆλ‹€.

2️⃣ Trie μž₯단점

  • 트라이(Trie)λŠ” λ¬Έμžμ—΄ 검색을 λΉ λ₯΄κ²Œ ν•œλ‹€.
  • λ¬Έμžμ—΄μ„ 탐색할 λ•Œ, ν•˜λ‚˜ν•˜λ‚˜μ”© μ „λΆ€ λΉ„κ΅ν•˜λ©΄μ„œ 탐색을 ν•˜λŠ” 것보닀 μ‹œκ°„ λ³΅μž‘λ„ μΈ‘λ©΄μ—μ„œ 훨씬 더 νš¨μœ¨μ μ΄λ‹€.
  • 각 λ…Έλ“œμ—μ„œ μžμ‹λ“€μ— λŒ€ν•œ 포인터듀을 λ°°μ—΄λ‘œ λͺ¨λ‘ μ €μž₯ν•˜κ³  μžˆλ‹€λŠ” μ μ—μ„œ μ €μž₯ κ³΅κ°„μ˜ 크기가 ν¬λ‹€λŠ” 단점도 μžˆλ‹€. (λ©”λͺ¨λ¦¬ μΈ‘λ©΄μ—μ„œ λΉ„νš¨μœ¨μ μΌ 수 있음!)

트라이의 치λͺ…적 단점은 곡간 λ³΅μž‘λ„μ—μ„œ λ‚˜νƒ€λ‚œλ‹€.

→ κ·Έ μ΄μœ λŠ” νŠΈλΌμ΄μ—μ„œ μ‹œκ°„λ³΅μž‘λ„κ°€ λ¬Έμžμ—΄μ˜ 길이만큼 λ‚˜μ˜€κΈ° μœ„ν•΄μ„œλŠ” λ‹€μŒ 문자λ₯Ό κ°€λ¦¬ν‚€λŠ” λ…Έλ“œκ°€ ν•„μš”ν•˜λ‹€.

 

λ¬Έμžμ—΄μ΄ λͺ¨λ‘ μ˜μ†Œλ¬Έμžλ‘œ 이루어져 μžˆλ‹€κ³  해도, μžμ‹ λ…Έλ“œλ₯Ό κ°€λ¦¬ν‚€λŠ” 26개의 포인터λ₯Ό μ €μž₯ν•΄μ•Ό ν•œλ‹€. μ΅œμ•…μ˜ κ²½μš°μ—λŠ” 집합에 ν¬ν•¨λ˜λŠ” λ¬Έμžμ—΄λ“€μ˜ 길이의 μ΄ν•©λ§ŒνΌ λ…Έλ“œκ°€ ν•„μš”ν•˜λ―€λ‘œ, 총 λ©”λͺ¨λ¦¬λŠ” O(포인터 크기 * 포인터 λ°°μ—΄ 개수 * 총 λ…Έλ“œμ˜ 개수)κ°€ λœλ‹€.

 

νŠΈλΌμ΄μ—μ„œ λ©”λͺ¨λ¦¬λ₯Ό μ ˆμ•½ν•˜κΈ° μœ„ν•œ νŠΈλ¦¬ν”Œ μ–΄λ ˆμ΄νŠΈλ¦¬(triple-array trie)와 같은 μ—¬λŸ¬ 기법듀이 κ°œλ°œλ˜μ–΄ μžˆμ§€λ§Œ 이듀은 μ½”ν…Œλ‚˜ μ•Œκ³ λ¦¬μ¦˜ λŒ€νšŒμ— μ‚¬μš©ν•˜κΈ°μ—λŠ” λ„ˆλ¬΄ λ³΅μž‘ν•˜κ³  μž‘μ„±ν•˜λŠ”λ° 였래 μ‹œκ°„μ΄ κ±Έλ¦¬λŠ” κ²½μš°κ°€ λŒ€λΆ€λΆ„μ΄λ‹€. λ•Œλ¬Έμ— λŒ€νšŒμ—μ„œ 트라이λ₯Ό μ“Έ 수 μžˆλŠ” κ²½μš°λŠ” λ‹€λ£¨λŠ” λ¬Έμžμ—΄μ˜ κ°œμˆ˜κ°€ κ·Έλ ‡κ²Œ λ§Žμ§€ μ•Šμ€ 경우둜 μ œν•œλœλ‹€.

 

μ°Έκ³ ) μ‹€μ œλ‘œ 카카였 μ½”ν…Œμ˜ νš¨μœ¨μ„± λ¬Έμ œμ—μ„œ 트라이(Trie)λ₯Ό μ‚¬μš©ν•˜λŠ” λ¬Έμ œκ°€ λ‚˜μ™”λŠ”λ° 전체 λ¬Έμžμ—΄μ˜ 길이λ₯Ό 10,000으둜 μ œν•œμ„ λ’€λ‹€.

 

3️⃣ Trie μ½”λ“œ κ΅¬ν˜„

[λ¬Έμžμ—΄ 집합을 Trie둜 μžλ£Œκ΅¬μ‘°ν™”ν–ˆμ„ λ•Œμ˜ ν˜•νƒœ]

μœ„ νŠΈλ¦¬μ—μ„œ 빨간색 ν…Œλ‘λ¦¬λ‘œ 된 λ…Έλ“œλŠ” λ¬Έμžμ—΄μ˜ λ§ˆμ§€λ§‰ 지점을 μ˜λ―Έν•©λ‹ˆλ‹€.이것이 ν•„μš”ν•œ μ΄μœ λŠ” "HE", "HELLO" 와 같이 μ•žμ˜ λ¬Έμžκ°€ μ€‘λ³΅λ˜λŠ” λ¬Έμžμ—΄μ„ μœ„ν•΄μ„œμΈλ°μš”, λ¬Έμžμ—΄ μ§‘ν•©μ—μ„œ "HE"λΌλŠ” λ¬Έμžμ—΄μ΄ μžˆλŠ”μ§€ ν™•μΈν•΄μ•Όν•œλ‹€κ³  ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. 그럼 탐색 과정은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  1. rootμ—μ„œλΆ€ν„° μ‹œμž‘ν•΄μ„œ child λ…Έλ“œ 쀑 Hλ₯Ό κ°€μ§€λŠ” λ…Έλ“œκ°€ μžˆλŠ”μ§€ μ°ΎμŠ΅λ‹ˆλ‹€.
  2. μ°Ύμ•˜λ‹€λ©΄, Hλ₯Ό κ°€μ§€λŠ” λ…Έλ“œλ‘œ μ΄λ™ν•©λ‹ˆλ‹€. (μ—†λ‹€λ©΄ returnν•΄μ„œ ν•΄λ‹Ή λ¬Έμžκ°€ μ—†λ‹€κ³  ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.)
  3. child λ…Έλ“œλ‘œ Eλ₯Ό κ°€μ§€λŠ” λ…Έλ“œκ°€ μžˆλŠ”μ§€ μ°ΎμŠ΅λ‹ˆλ‹€.
  4. μ°Ύμ•˜λ‹€λ©΄, ν•΄λ‹Ή Eκ°€ λ¬Έμžμ—΄μ˜ λμž„μ„ μ•Œλ¦¬λŠ” flag값이 μ„€μ •λ˜μ–΄ μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
  5. μ„€μ •λ˜μ–΄ μžˆλ‹€λ©΄, λ¬Έμžμ—΄ 집합에 ν•΄λ‹Ή λ¬Έμžμ—΄μ΄ μ‘΄μž¬ν•˜λŠ” κ²ƒμž„μ„ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.
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;
        }
    }
}

 

4️⃣ Trie κ΄€λ ¨ μ•Œκ³ λ¦¬μ¦˜ 문제


🌐 참고 링크

[μ•Œκ³ λ¦¬μ¦˜/ 자료ꡬ쑰] 트라이(Trie) λ¬Έμžμ—΄ 탐색 트리 κ°œλ… 정리 (Java)

[자료ꡬ쑰] 트라이 (Trie)

[자료ꡬ쑰] Trie(트라이)

[자료ꡬ쑰] 트라이(Trie) 자료ꡬ쑰