Skip to content

Latest commit

ย 

History

History
115 lines (85 loc) ยท 5.45 KB

File metadata and controls

115 lines (85 loc) ยท 5.45 KB

ํŠธ๋ฆฌ(Tree)์˜ ์‘์šฉ - ํŠธ๋ผ์ด(Trie)

ํŠธ๋ผ์ด(Trie)๋Š” ๋ฌธ์ž์—ด์„ ๋น ๋ฅด๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ž๋ฃŒ ๊ตฌ์กฐ๋กœ, ๋‹จ์–ด ์‚ฌ์ „๊ณผ ๊ฐ™์€ ๊ฐœ๋…์ด๋ผ๊ณ  ๊ธฐ์–ตํ•ด๋‘๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.
ํŠน์ • ๋‹จ์–ด๋ฅผ ์ฐพ๊ณ  ์‹ถ์€๋ฐ ๊ทธ ๊ฒ€์ƒ‰ ์‹œ๊ฐ„์ด ๋นจ๋ž์œผ๋ฉด ํ•  ๋•Œ, ์šฐ๋ฆฌ๋Š” ํŠธ๋ผ์ด(Trie) ๊ตฌ์กฐ๋ฅผ ๋– ์˜ฌ๋ ค๋ณด์ž.

๊ฒ€์ƒ‰์–ด ์ž๋™ ์™„์„ฑ, ์‚ฌ์ „์—์„œ ์ฐพ๊ธฐ, ๋ฌธ์ž์—ด ๊ฒ€์‚ฌ ๋“ฑ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํŠธ๋ผ์ด(Trie)

Prefix Tree, Digital Search Tree, Retrieval Tree ๋ผ๊ณ ๋„ ๋ถ€๋ฅธ๋‹ค.

  • ๋ฌธ์ž์—ด์„ ์ €์žฅํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ํƒ์ƒ‰ํ•˜๊ธฐ ์œ„ํ•œ ํŠธ๋ฆฌ ํ˜•ํƒœ์˜ ์ž๋ฃŒ๊ตฌ์กฐ
  • K์ง„ ํŠธ๋ฆฌ ๊ตฌ์กฐ
  • ๋‹จ์–ด ์‚ฌ์ „์„ ํŠธ๋ผ์ด๋กœ ์ƒ์„ฑ, ๊ทธ ํ›„ ์ฐพ์„ ๋‹จ์–ด๋ฅผ ํŠธ๋ผ์ด๋ฅผ ์‚ฌ์šฉํ•ด ๊ฒ€์ƒ‰
  • ํŠธ๋ผ์ด์˜ root ๋…ธ๋“œ๋Š” ํ•ญ์ƒ ๋นˆ ๋ฌธ์ž์—ด

Trie

์œ„ ๊ทธ๋ฆผ์„ ์‚ดํŽด๋ณด๋ฉด, ํŠธ๋ฆฌ์˜ ๊นŠ์ด์— ๋”ฐ๋ผ ๋‹จ์–ด๋ฅผ 1๊ธ€์ž, 2๊ธ€์ž, 3๊ธ€์ž์”ฉ ์ €์žฅํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. (root ๋…ธ๋“œ๋Š” ๋นˆ ๋ฌธ์ž์—ด)

  • 'tea' ์ฐพ๊ธฐ : ํŠธ๋ฆฌ๋ฅผ ๋”ฐ๋ผ ๊ฐ€์„œ t, e, a ๋ฅผ ์ฐพ๋Š”๋‹ค.
  • 'tee' ์ฐพ๊ธฐ : ํŠธ๋ฆฌ๋ฅผ ๋”ฐ๋ผ ๊ฐ”์„ ๋•Œ t, e ๋‹ค์Œ e๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—†๋Š” ๊ธ€์ž์ด๋‹ค.
  • 'te' ์ฐพ๊ธฐ : t, e๊นŒ์ง€๋Š” ์žˆ์ง€๋งŒ e๊ฐ€ ๋‹จ์–ด์˜ ๋์ด ์•„๋‹ˆ๋ฏ€๋กœ ์—†๋Š” ๊ธ€์ž์ด๋‹ค. (์ฆ‰ ํŠธ๋ผ์ด์—๋Š” ๋‹จ์–ด์˜ ๋์„ ์•Œ๋ฆฌ๋Š” flag๊ฐ€ ํ•„์š”ํ•˜๋‹ค.)

์‹œ๊ฐ„ ๋ณต์žก๋„

์ œ์ผ ๊ธด ๋‹จ์–ด์˜ ๊ธธ์ด๋ฅผ M, ์ด ๋‹จ์–ด๋“ค์˜ ์ˆ˜๋ฅผ N์ด๋ผ๊ณ  ํ•  ๋•Œ,

  • ํŠธ๋ผ์ด ์ƒ์„ฑ ์‹œ ์‹œ๊ฐ„ ๋ณต์žก๋„ : O(N *M) ๋‹จ์–ด ํ•˜๋‚˜๋ฅผ ์‚ฝ์ž…ํ•˜๋Š”๋ฐ ๊ฐ€์žฅ ๊ธด ๋‹จ์–ด์˜ ๊ธธ์ด M ๋งŒํผ ๊ฑธ๋ฆฌ๋ฏ€๋กœ O(M)์ด๊ณ , ์ด๋ฅผ N๊ฐœ ๋„ฃ์œผ๋ฏ€๋กœ O(N*M)์ด๋‹ค.
  • ๋‹จ์–ด ๊ฒ€์ƒ‰ ์‹œ ์‹œ๊ฐ„ ๋ณต์žก๋„ : O(M) ๊ฐ€์žฅ ๊ธด ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๋งŒํผ ๊ฑธ๋ฆฌ๋ฏ€๋กœ O(M)์ด๋‹ค.

๋‹จ์–ด๋ฅผ ํ•˜๋‚˜์”ฉ ๋น„๊ตํ•˜๋ฉฐ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์‹œ๊ฐ„์ ์œผ๋กœ ํ›จ์”ฌ ํšจ์œจ์ ์ด์ง€๋งŒ,
๊ฐ ๋…ธ๋“œ์—์„œ ๊ทธ ์ž์‹ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ฐฐ์—ด๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๊ทธ ๋…ธ๋“œ๋“ค์˜ ๊ฐœ์ˆ˜๋ฅผ ์ƒ๊ฐํ•ด๋ดค์„ ๋•Œ ๊ณต๊ฐ„ ๋ณต์žก๋„ ์ธก๋ฉด์—์„œ๋Š” ๋น„ํšจ์œจ์ ์ด๋‹ค.

ํŠธ๋ผ์ด ๊ตฌํ˜„ํ•˜๊ธฐ

ํŠธ๋ผ์ด ๋…ธ๋“œ ์„ค๊ณ„

ํŠธ๋ผ์ด ๋…ธ๋“œ์— ํ•„์š”ํ•œ ์ •๋ณด๋Š” ์ž์‹ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ •๋ณด children, ํ˜„์žฌ ๋…ธ๋“œ๊ฐ€ ๋‹จ์–ด์˜ ๋์ธ์ง€ ์—ฌ๋ถ€ isEnd ์ด ๋‘ ๊ฐ€์ง€์ด๋‹ค.
์˜ˆ์ œ ์ฝ”๋“œ๋Š” ์•ŒํŒŒ๋ฒณ ๋Œ€๋ฌธ์ž๋งŒ ์ €์žฅํ•˜๋Š” ํŠธ๋ผ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ๋‹ค.
๊ตฌํ˜„์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด getChild, hasChild ๋ฉ”์„œ๋“œ๋„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

class TrieNode {
    TrieNode[] children = new TrieNode[26]; // ์•ŒํŒŒ๋ฒณ ๋Œ€๋ฌธ์ž๋งŒ
    boolean isEnd;

    TrieNode getChild(char c) {
        return children[c - 'A'];
    }

    boolean hasChild(char c) {
        return children[c - 'A'] != null;
    }
}

ํŠธ๋ผ์ด ์ƒ์„ฑํ•˜๊ธฐ (๋‹จ์–ด ์‚ฌ์ „ ๋งŒ๋“ค๊ธฐ)

๋‹จ์–ด ์‚ฌ์ „์˜ ๋‹จ์–ด๋ฅผ ํŠธ๋ผ์ด์— ํ•˜๋‚˜์”ฉ ์‚ฝ์ž…ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

  1. ๋ฃจํŠธ ๋…ธ๋“œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ๋‹จ์–ด์˜ ์ฒซ ๊ธ€์ž๋ถ€ํ„ฐ ํŠธ๋ผ์ด๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค.
  2. ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ ์ค‘ ํ˜„์žฌ ํƒ์ƒ‰ ์ค‘์ธ ๋ฌธ์ž๊ฐ€ ์žˆ๋‹ค๋ฉด, ๊ทธ ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™ํ•œ๋‹ค.
  3. ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ ์ค‘ ํ˜„์žฌ ํƒ์ƒ‰ ์ค‘์ธ ๋ฌธ์ž๊ฐ€ ์—†๋‹ค๋ฉด, ์ƒˆ๋กœ์šด ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
  4. ๋‹จ์–ด์˜ ๋งˆ์ง€๋ง‰ ๊ธ€์ž๊นŒ์ง€ ์™”๋‹ค๋ฉด, isEnd๋ฅผ true๋กœ ํ•ด์ฃผ๋ฉด ๋‹จ์–ด์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํŠธ๋ผ์ด์— ์ €์žฅ๋œ๋‹ค.

ํŠธ๋ผ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฒ€์ƒ‰ํ•˜๊ธฐ

  1. ๋ฃจํŠธ ๋…ธ๋“œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ๋‹จ์–ด์˜ ์ฒซ ๊ธ€์ž๋ถ€ํ„ฐ ํŠธ๋ผ์ด๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค.
  2. ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ ์ค‘ ํ˜„์žฌ ํƒ์ƒ‰ ์ค‘์ธ ๋ฌธ์ž๊ฐ€ ์žˆ๋‹ค๋ฉด, ๊ทธ ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™ํ•œ๋‹ค.
  3. ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ ์ค‘ ํ˜„์žฌ ํƒ์ƒ‰ ์ค‘์ธ ๋ฌธ์ž๊ฐ€ ์—†๋‹ค๋ฉด, return false
  4. ๋‹จ์–ด์˜ ๋งˆ์ง€๋ง‰ ๊ธ€์ž๊นŒ์ง€ ์™”๋Š”๋ฐ, isEnd๊ฐ€ false๋ผ๋ฉด return false
  5. ๋‹จ์–ด์˜ ๋งˆ์ง€๋ง‰ ๊ธ€์ž๊นŒ์ง€ ์™”๊ณ , isEnd๊ฐ€ true๋ผ๋ฉด return true

ํŠธ๋ผ์ด ์ƒ์„ฑ, ๊ฒ€์ƒ‰์— ๊ด€ํ•œ Trie ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

class Trie {
    TrieNode root = new TrieNode(); // ๋ฃจํŠธ ๋…ธ๋“œ ์ƒ์„ฑ

    void insert(String word) {
        TrieNode current = root;
        for (int i = 0; i < word.length(); i++) { // ๋‹จ์–ด์˜ ์ฒซ ๊ธ€์ž ~ ๋ ๊ธ€์ž๊นŒ์ง€ ํƒ์ƒ‰
            char c = word.charAt(i);
            if (!current.hasChild(c)) { // ํ•ด๋‹น ๋ฌธ์ž์— ๋Œ€ํ•œ ์ž์‹ ๋…ธ๋“œ ์žˆ๋Š”์ง€ ๊ฒ€์ƒ‰ ํ›„ ๊ทธ ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™
                current.children[c - 'A'] = new TrieNode();
            }
            current = current.getChild(c);
        }
        current.isEnd = true; // ๋ ๊ธ€์ž์ž„์„ ์•Œ๋ฆฌ๋Š” ํ”Œ๋ž˜๊ทธ ์ ์šฉ
    }

    boolean checkWord(String word) {
        TrieNode current = root;
        for (int i = 0; i < word.length(); i++) { // ๋‹จ์–ด์˜ ์ฒซ ๊ธ€์ž ~ ๋ ๊ธ€์ž๊นŒ์ง€ ํƒ์ƒ‰
            char c = word.charAt(i);
            if (current.hasChild(c)) { // ํ•ด๋‹น ๋ฌธ์ž์— ๋Œ€ํ•œ ์ž์‹ ๋…ธ๋“œ ์žˆ๋‹ค๋ฉด ๊ทธ ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™
                current = current.getChild(c);
            } else { // ํ•ด๋‹น ๋ฌธ์ž์— ๋Œ€ํ•œ ์ž์‹ ๋…ธ๋“œ ์—†์œผ๋ฉด return false
                return false;
            }
        }
        return current.isEnd; // ๋๊นŒ์ง€ ์™”๋Š”๋ฐ isEnd๋ผ๋ฉด true, ์•„๋‹ˆ๋ฉด false
    }
}

์˜ˆ์ œ ์ฝ”๋“œ ๋ฐ”๋กœ ๊ฐ€๊ธฐ โ–ถ๏ธ TrieTest.java

๊ด€๋ จ ๋ฌธ์ œ ํ’€์–ด๋ณด๊ธฐ