trie - changicho/algorithm-training GitHub Wiki

ํŠธ๋ผ์ด

๋ฌธ์ œ

์„ค๋ช…

ํŠธ๋ผ์ด๋Š” ๋ฌธ์ž์—ด์„ ํšจ์œจ์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ  ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” K์ง„ ํŠธ๋ฆฌ์˜ ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.

์›ํ•˜๋Š” ๋ฌธ์ž์—ด์„ ์ฐพ๋Š” ๋ฐ ๋“ค์–ด๊ฐ€๋Š” ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(N)์ด๋‹ค.

๊ฐ ๋‹จ๊ณ„๋งˆ๋‹ค ๋ฌธ์ž์—ด๋“ค์„ key๋กœ ์„ค์ •ํ•˜๊ณ  ์ดํ›„ ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํƒ์ƒ‰์„ ์ตœ์ ํ™”ํ•œ๋‹ค.

์ด๋•Œ ์ค‘๋ณต๋œ ๋‹จ๊ณ„์—์„œ ๋ฌธ์ž์—ด์ด ์–ด๋–จ๋•Œ๋Š” ๋งˆ์ง€๋ง‰ ๋ฌธ์ž์—ด์ผ์ˆ˜๋„, ์•„๋‹์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— boolean์œผ๋กœ ์ด ๋‹จ๊ณ„๊ฐ€ ๋์ธ์ง€ ์—ฌ๋ถ€๋˜ํ•œ ์ €์žฅํ•œ๋‹ค.

๋ฃจํŠธ ๋…ธ๋“œ์˜ ๊ฒฝ์šฐ key๊ฐ’์ด ์—†์Œ์— ์œ ์˜ํ•œ๋‹ค.

๊ตฌํ˜„

TrieNode์˜ ๊ตฌํ˜„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

// use array
struct TrieNode {
  // ๋ชจ๋“  char์— ๋Œ€ํ•ด ์„ ์–ธํ–ˆ์œผ๋ฏ€๋กœ ๋ฌธ์ œ์— ์ฃผ์–ด์ง„ 26์ž์— ๋Œ€ํ•ด์„œ๋งŒ ์ตœ์ ํ™”๋„ ๊ฐ€๋Šฅํ•˜๋‹ค
  struct TrieNode *children[256] = {
      NULL,
  };

  bool isEnd = false;
};

// use hashmap
struct TrieNode {
  unordered_map<char, TrieNode *> children;
  bool isEnd;

  TrieNode() { isEnd = false; }
};

์ด๋ฅผ ์ด์šฉํ•ด ํŠธ๋ผ์ด๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

class Trie {
 private:
  struct TrieNode {
    unordered_map<char, TrieNode *> children;
    bool isEnd;

    TrieNode() { isEnd = false; }
  };

  TrieNode *root = new TrieNode;

 public:
  void insert(string word) {
    TrieNode *node = root;

    for (char c : word) {
      if (!node->children[c]) {
        node->children[c] = new TrieNode;
      }

      node = node->children[c];
    }

    node->isEnd = true;
  }

  bool search(string word) {
    TrieNode *node = root;

    for (char c : word) {
      if (!node->children[c]) {
        return false;
      }

      node = node->children[c];
    }

    return node && node->isEnd;
  }

  bool startsWith(string prefix) {
    TrieNode *node = root;

    for (char c : prefix) {
      if (!node->children[c]) {
        return false;
      }

      node = node->children[c];
    }

    return node;
  }
};

์‚ญ์ œ ๊ฐ€๋Šฅํ•œ ํŠธ๋ผ์ด

class Trie {
 private:
  struct TrieNode {
    unordered_map<char, TrieNode *> children;
    bool isEnd;

    TrieNode() { isEnd = false; }
  };

  TrieNode *root = new TrieNode;

  bool isEmpty(TrieNode *cur) {
    if (cur->children.size() > 0) return false;
    return true;
  }

  void erase(string &word, int index, TrieNode *cur) {
    int length = word.length();

    if (index == length) {
      cur->isEnd = false;
      return;
    }

    int key = word[index];

    erase(word, index + 1, cur->children[key]);

    if (isEmpty(cur->children[key])) {
      cur->children[key] = NULL;
      delete cur->children[key];
    }
  }

 public:
  void insert(string word) {
    TrieNode *node = root;

    for (char c : word) {
      if (!node->children[c]) {
        node->children[c] = new TrieNode;
      }

      node = node->children[c];
    }

    node->isEnd = true;
  }

  bool has(string word) {
    TrieNode *node = root;

    for (char c : word) {
      if (!node->children[c]) {
        return false;
      }

      node = node->children[c];
    }

    return node && node->isEnd;
  }

  bool startsWith(string prefix) {
    TrieNode *node = root;

    for (char c : prefix) {
      if (!node->children[c]) {
        return false;
      }

      node = node->children[c];
    }

    return node;
  }

  void erase(string word) { erase(word, 0, root); }
};