Skip to content

Latest commit

ย 

History

History
302 lines (213 loc) ยท 11.6 KB

0727-trie-dfs.md

File metadata and controls

302 lines (213 loc) ยท 11.6 KB

2020.07.27.Mon

๐Ÿ“š๊ณต๋ถ€ํ•œ ๊ฑฐ List๐Ÿ“š

  • ์ข…๋งŒ๋ถ - 26. ํŠธ๋ผ์ด
  • ์ข…๋งŒ๋ถ - (์ถ”๊ฐ€) ๊ทธ๋ž˜ํ”„๋กœ ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ ์œ ํ˜•
  • ์ข…๋งŒ๋ถ - 28. ๊ทธ๋ž˜ํ”„์˜ ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰

๐ŸŒด[์ข…๋งŒ๋ถ] ํŠธ๋ผ์ด๐ŸŒด

๐ŸŒฑ ํŠธ๋ผ์ด(Trie)๋ž€?**

  • ๋ฌธ์ž์—ด์˜ ์ง‘ํ•ฉ์„ ํ‘œํ˜„ํ•˜๋Š” ํŠธ๋ฆฌ ์ž๋ฃŒ๊ตฌ์กฐ๋กœ, ์ง‘ํ•ฉ ๋‚ด์—์„œ ์›ํ•˜๋Š” ์›์†Œ๋ฅผ ์ฐพ๋Š” ์ž‘์—…์„ O(M) (M์€ ๋ฌธ์ž์—ด์˜ ์ตœ๋Œ€ ๊ธธ์ด) ๋งŒ์— ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

  • ์ง‘ํ•ฉ์— ํฌํ•จ๋œ ๋ฌธ์ž์—ด์˜ ์ ‘๋‘์‚ฌ๋“ค์— ๋Œ€์‘๋˜๋Š” ๋…ธ๋“œ๋“ค์ด ์„œ๋กœ ์—ฐ๊ฒฐ๋œ ํŠธ๋ฆฌ์ด๋‹ค.

๐ŸŒฑ ํŠธ๋ผ์ด์˜ ์ค‘์š”ํ•œ ์†์„ฑ

  • ํŠธ๋ผ์ด์˜ root๋Š” ํ•ญ์ƒ ๊ธธ์ด 0์ธ ๋ฌธ์ž์—ด์— ๋Œ€์‘๋˜๊ณ , ๋…ธ๋“œ์˜ ๊นŠ์ด๊ฐ€ ๊นŠ์–ด์งˆ ๋•Œ๋งˆ๋‹ค ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๊ฐ€ 1์”ฉ ๋Š˜์–ด๋‚œ๋‹ค.
  • ์ข…๋ฃŒ๋…ธ๋“œ : ํ•ด๋‹น ์œ„์น˜์— ๋Œ€์‘๋˜๋Š” ๋ฌธ์ž์—ด์ด ํŠธ๋ผ์ด๊ฐ€ ํ‘œํ˜„ํ•˜๋Š” ์ง‘ํ•ฉ์— ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋Š” ์˜๋ฏธ
  • ๋ฃจํŠธ์—์„œ ํ•œ ๋…ธ๋“œ๊นŒ์ง€ ๋‚ด๋ ค๊ฐ€๋Š” ๊ฒฝ๋กœ์—์„œ ๋งŒ๋‚˜๋Š” ๊ธ€์ž๋“ค์„ ๋ชจ์œผ๋ฉด ํ•ด๋‹น ๋…ธ๋“œ์— ๋Œ€์‘๋˜๋Š” ๋ฌธ์ž์—ด์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
  • ํŠธ๋ผ์ด์˜ ๋…ธ๋“œ ๊ฐ์ฒด = ์ž์† ๋…ธ๋“œ๋“ค์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ ๋ชฉ๋ก + ์ข…๋ฃŒ๋…ธ๋“œ์ธ์ง€ ๋‚˜ํƒ€๋‚ด๋Š” boolean๊ฐ’ ๋ณ€์ˆ˜

โŒจ๏ธํŠธ๋ผ์ด์˜ ๋…ธ๋“œ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ์ฒด์˜ ์„ ์–ธ

TrieNode : ํŠธ๋ผ์ด์˜ ๋…ธ๋“œ ํ•˜๋‚˜๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ์ฒด

ALPHABET : ๋ฌธ์ž์—ด์— ์ถœํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ž์˜ ๊ฐœ์ˆ˜

toNumber() : ์ฃผ์–ด์ง„ ๋ฌธ์ž๋ฅผ ์ˆซ์ž๋กœ ๋ณ€ํ™˜ (0~ALPHABET-1)

insert() : ํŠธ๋ผ์ด์— ์ƒˆ ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜๋Š” ํ•จ์ˆ˜

find() : ํŠธ๋ผ์ด์— ํŠน์ • ๋ฌธ์ž์—ด์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜

//ํ•„์š”ํ•œ ํ—ค๋”
#include <cstring> //memset

๐Ÿšฉ์ฃผ์„ ๋ฏธ์™„์„ฑ๋ถ€๋ถ„์žˆ์Œ

const int ALPHABETS = 26; //์ „์ฒด ์•ŒํŒŒ๋ฒณ ๋Œ€๋ฌธ์ž ๊ฐœ์ˆ˜๋Š” 26๊ฐœ
int toNumber(char ch) {
  return ch - 'A';
}
struct TrieNode {
  TrieNode* children[ALPHABETS]; //์ž์†๋…ธ๋“œ๋“ค์˜ ํฌ์ธํ„ฐ ๋ชฉ๋ก(๋™์ ๋ฐฐ์—ด์ด ์•„๋‹Œ ๊ณ ์ •๋ฐฐ์—ด ์‚ฌ์šฉ)
  bool terminal; //์ข…๋ฃŒ๋…ธ๋“œ์ธ๊ฐ€?
  TrieNode() : terminal(false) {//์ƒ์„ฑ์ž(๋ชจ๋“  ํŠธ๋ผ์ด ๋…ธ๋“œ์˜ ์ข…๋ฃŒ๋…ธ๋“œ์—ฌ๋ถ€๋ฅผ false๋กœ ์„ค์ •)
    memset(children, 0, sizeof(children));  //์ž์†๋“ค์˜ ํฌ์ธํ„ฐ ๋ชฉ๋ก์„ 0์œผ๋กœ ์ดˆ๊ธฐํ™”
  }
  ~TrieNode() { //์†Œ๋ฉธ์ž
    for(int i=0; i<ALPHABETS; ++i) {
      if(children[i]) delete children[i]; 
    }
  }
  //์ด ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ๋กœ ํ•˜๋Š” ํŠธ๋ฆฌ์— ๋ฌธ์ž์—ด key๋ฅผ ์ถ”๊ฐ€
  void insert(const char* key) {
    if(*key == 0) terminal = true; //๋ฌธ์ž์—ด์ด ๋๋‚˜๋ฉด ์ข…๋ฃŒ๋…ธ๋“œ์—ฌ๋ถ€๋ฅผ ์ฐธ์œผ๋กœ ๋ฐ”๊พผ๋‹ค
    else {
      int next = toNumber(*key);//๋ฌธ์ž์—ด์„ ์ˆซ์ž๋กœ ๋ณ€ํ™˜ ํ›„ next์— ์ €์žฅ
      if(children[next] == NULL) //next์˜ ์ž์‹๋…ธ๋“œ๊ฐ€ ์—†๋‹ค๋ฉด
        children[next] = new TrieNode(); //์ž์‹๋…ธ๋“œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค
      children[next]->insert(key+1);//์ž์‹๋…ธ๋“œ๊ฐ์ฒด๋กœ ์žฌ๊ท€ํ˜ธ์ถœ
    }
  }
  //์ด ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ๋กœ ํ•˜๋Š” ํŠธ๋ผ์ด์— ๋ฌธ์ž์—ด key์™€ ๋Œ€์‘๋˜๋Š” ๋…ธ๋“œ๋ฅผ ์ฐพ๊ณ  ์—†์œผ๋ฉด NULL๋ฐ˜ํ™˜
  TrieNode* find(const char* key) { 
    if(*key == 0) return this; //๋ฌธ์ž์—ด์ด ๋๋‚ฌ๋‹ค๋ฉด this๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค(?)
    int next = toNumber(*key); //๋ฌธ์ž์—ด์„ ์ˆซ์ž๋กœ ๋ณ€ํ™˜ ํ›„ next์— ์ €์žฅ
    if(children[next]==NULL) //์ž์‹๋…ธ๋“œ๊ฐ€ ์—†๋‹ค๋ฉด
      return NULL; //๋Œ€์‘๋˜๋Š” ๋…ธ๋“œ๊ฐ€ ์—†๋Š” ๊ฒƒ์ด๋ฏ€๋กœ NULL๋ฐ˜ํ™˜
    return children[next]->find(key+1);//์ž์‹๋…ธ๋“œ ์žฌ๊ท€ํ˜ธ์ถœ
  }
}

๐ŸŒด [์ข…๋งŒ๋ถ] ๊ทธ๋ž˜ํ”„๋กœ ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์œ ํ˜• ๐ŸŒด

๐ŸŒฑ์ ˆ๋‹จ์  ์ฐพ๊ธฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ์ฒ ๋„๋ง์—์„œ ํ•œ ์—ญ์ด ํ์‡„๋œ ๊ฒฝ์šฐ, ์ฒ ๋„๋ง ์ „์ฒด๊ฐ€ ๋‘ ๊ฐœ์ด์ƒ์œผ๋กœ ์ชผ๊ฐœ์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š”์ง€ ์•Œ์•„๋‚ด๋Š” ๋ฌธ์ œ
    • ์—ญ์„ ์ •์ ์œผ๋กœ, ์ฒ ๋กœ๋ฅผ ๊ฐ„์„ ์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค๊ณ  ์ ˆ๋‹จ์  ์ฐพ๊ธฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐ

๐ŸŒฑ๊ทธ๋ž˜ํ”„์˜ ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰

  • ์นœ๋ถ„๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฌธ์ œ(๋ช‡ ๋‹ค๋ฆฌ ๊ฑด๋„ˆ์•ผ ์•„๋Š” ์‚ฌ์ด์ธ์ง€, ํ•œ ๋‹ค๋ฆฌ๊ฑด๋„ˆ ์•„๋Š” ์‚ฌ๋žŒ์€ ๋ช‡ ๋ช…์ธ์ง€)
    • ์‚ฌ๋žŒ์„ ์ •์ ์œผ๋กœ, ๊ด€๊ณ„๋ฅผ ๊ฐ„์„ ์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทธ๋ž˜ํ”„์˜ ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰์œผ๋กœ ํ•ด๊ฒฐ

๐ŸŒฑ์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ๋‘ ์ปดํ“จํ„ฐ ๊ฐ„ ์ „์†ก ์šฉ๋Ÿ‰ ๊ณ„์‚ฐํ•˜๋Š” ๋ฌธ์ œ(์ „์†ก์šฉ๋Ÿ‰์€ ์—ฐ๊ฒฐ๋œ ๊ฒƒ๋“ค ์ค‘ ์ตœ์†Œ ์ „์†ก์šฉ๋Ÿ‰์„ ๊ฐ–๋Š” ์ผ€์ด๋ธ”์— ์ขŒ์šฐ๋œ๋‹ค๊ณ  ๊ฐ€์ •)
    • ์ปดํ“จํ„ฐ์™€ ๋ผ์šฐํ„ฐ๋ฅผ ์ •์ ์œผ๋กœ, ์ผ€์ด๋ธ”์„ ๊ฐ„์„ ์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ ํ›„, MST์ด์šฉํ•˜์—ฌ ํ•ด๊ฒฐ

๐ŸŒฑ์˜ค์ผ๋Ÿฌ ๊ฒฝ๋กœ(์ž๋งคํ’ˆ: ์˜ค์ผ๋Ÿฌ ์„œํ‚ท)

  • ํ•œ ๋ถ“ ๊ทธ๋ฆฌ๊ธฐ ๋ฌธ์ œ
    • ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์„ ์‘์šฉํ•œ ์˜ค์ผ๋Ÿฌ ๊ฒฝ๋กœ๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐ

๐ŸŒฑ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ๊ฐ€์ค‘์น˜์˜ ํ•ฉ์ด ์Œ์ˆ˜์ธ ์‚ฌ์ดํด ์ฐพ๊ธฐ ๋ฌธ์ œ
  • ์ตœ์†Œํ•œ์œผ๋กœ ํƒ€์ผ์„ ์›€์ง์—ฌ 15-ํผ์ฆ์„ ํ‘ธ๋Š” ๋ฌธ์ œ

๐ŸŒฑ์œ„์ƒ์ •๋ ฌ

  • ์–ด๋–ค ์ˆœ์„œ๋Œ€๋กœ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š”์ง€ ๊ณ„์‚ฐํ•˜๋Š” ๋ฌธ์ œ
    • ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์„ ์‘์šฉํ•œ ์œ„์ƒ์ •๋ ฌ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ์ด์šฉ

๐ŸŒฑ์ด๋ถ„ ๋งค์นญ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ์ผ๋ถ€ ์นธ์ด ๋ง‰ํ˜€์žˆ๋Š” ๋ธ”๋ก๋ฌธ์ œ์—์„œ ๋ง‰ํ˜€์žˆ์ง€ ์•Š์€ ๋ชจ๋“  ์นธ์— ๋ธ”๋ก์„ ๋†“๋Š” ๋ฌธ์ œ
    • ์ƒํ•˜์ขŒ์šฐ๋กœ ์ธ์ ‘ํ•œ ์นธ๋“ค์„ ๊ฐ„์„ ์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ถ„ ๋งค์นญ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ํ•ด๊ฒฐ

๐ŸŒฑ๊ฐ• ๊ฒฐํ•ฉ์„ฑ ๋ฌธ์ œ (2-SAT)

  • ๋งŒ์กฑ์„ฑ ๋ฌธ์ œ : ํšŒ์˜์‹ค ๋ฐฐ์ •๋ฌธ์ œ

๐ŸŒฑ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰

  • ๋‘ ์ •์ ์ด ์„œ๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฌธ์ œ
  • ์—ฐ๊ฒฐ๋œ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ์ˆ˜ ์„ธ๋Š” ๋ฌธ์ œ
  • ์œ„์ƒ์ •๋ ฌ
  • ์˜ค์ผ๋Ÿฌ ๊ฒฝ๋กœ

๐ŸŒด [์ข…๋งŒ๋ถ] ๊ทธ๋ž˜ํ”„์˜ ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰ ๐ŸŒด

๐ŸŒฑ ์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ(Eulerian Trail)

๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ๊ฐ„์„ ์„ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ์”ฉ ์ง€๋‚˜์ง€๋งŒ, ์‹œ์ž‘์ ๊ณผ ๋์ ์ด ๋‹ค๋ฅธ ๊ฒฝ๋กœ

์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ์˜ ์กด์žฌ ์กฐ๊ฑด : ์‹œ์ž‘์ ๊ณผ ๋์ ์„ ์ œ์™ธํ•œ ๋ชจ๋“  ์ ์€ ์ง์ˆ˜์ ์ด๊ณ  ์‹œ์ž‘์ ๊ณผ ๋์ ์€ ํ™€์ˆ˜์ ์ด์–ด์•ผ ํ•œ๋‹ค.

๐ŸŒฑ ํ•ด๋ฐ€ํ† ๋‹ˆ์•ˆ ๊ฒฝ๋กœ(Hamiltonian Path)

๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ์ •์ ์„ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ์”ฉ ์ง€๋‚˜๋Š” ๊ฒฝ๋กœ

๋ชจ๋“  ์ •์ ์˜ ๋ฐฐ์—ด์„ ํ•˜๋‚˜ํ•˜๋‚˜ ์‹œ๋„ํ•˜๋ฉฐ ์ด๋“ค์ด ๊ฒฝ๋กœ๊ฐ€ ๋˜๋Š”์ง€ ํ™•์ธํ•˜๋Š”, ์กฐํ•ฉํƒ์ƒ‰์œผ๋กœ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. (๐Ÿคฆโ€โ™€๏ธ๋ฌธ์ œ์  : ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋„ˆ๋ฌด ๋งŽ์€ ํ›„๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Œ)


๐Ÿ“ ์˜ˆ์ œ::๋‹จ์–ด ์ œํ•œ ๋๋ง์ž‡๊ธฐ(ID: WORDCHAIN)

๋‹จ์–ด๋“ค์˜ ๋ชฉ๋ก์ด ์ฃผ์–ด์งˆ ๋•Œ, ๋‹จ์–ด๋“ค์„ ์ „๋ถ€ ์‚ฌ์šฉํ•˜๊ณ  ๊ฒŒ์ž„์ด ๋๋‚  ์ˆ˜ ์žˆ๋Š”์ง€, ๊ทธ๋Ÿด ์ˆ˜ ์žˆ๋‹ค๋ฉด ์–ด๋–ค ์ˆœ์„œ๋กœ ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ฌธ์ œ

โšก๏ธkeypointโšก๏ธ

  1. ์ž…๋ ฅ์— ์ฃผ์–ด์ง„ ๊ฐ ๋‹จ์–ด๋ฅผ ๊ฐ„์„ ์œผ๋กœ ๊ฐ–๋Š” ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค๊ณ , ์ •์ ์€ ๊ฐ„์„ ์˜ ์ฒซ ๊ธ€์ž์™€ ๋งˆ์ง€๋ง‰ ๊ธ€์ž๋กœ ํ•œ๋‹ค.

โŒจ๏ธ ๋๋ง์ž‡๊ธฐ ๋ฌธ์ œ์˜ ์ž…๋ ฅ์„ ๊ทธ๋ž˜ํ”„๋กœ ๋งŒ๋“ค๊ธฐ

adj : ๊ทธ๋ž˜ํ”„์˜ ์ธ์ ‘ํ–‰๋ ฌ

indegree, outdegree : ๊ฐ๊ฐ ์ •์ ์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ๊ฐ„์„ ์˜ ์ˆ˜, ๋‚˜๊ฐ€๋Š” ๊ฐ„์„ ์˜ ์ˆ˜

graph : ๋‘ ์ •์  ์‚ฌ์ด๋ฅผ ์ž‡๋Š” ๊ฐ„์„ ๋“ค์ด ๋‚˜ํƒ€๋‚ด๋Š” ๋‹จ์–ด์˜ ๋ชฉ๋ก

vector<vector<int>> adj;
vector<string> graph[26][26];
vector<int> indegree, outdegree;

void makeGraph(const vector<string>& words) {
  for(int i=0; i<26; ++i) {
    for(int j=0; j<26; ++j) 
      graph[i][j].clear();
  }
  adj = vector<vector<int>>(26, vector<int>(26,0));
  indegree = outdegree = vector<int>(26,0);
  for(int i=0; i<words.size(); ++i) {
    int a = words[i][0] - 'a';
    int b = words[i][words[i].size()-1] - 'a';
    graph[a][b].push_back(words[i]);
    adj[a][b]++;
    outdegree[a]++;
    indegree[b]++;
  }
}

๐ŸŒฑ ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์—์„œ์˜ ์˜ค์ผ๋Ÿฌ ์„œํ‚ท/ํŠธ๋ ˆ์ผ

๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์—์„œ ์˜ค์ผ๋Ÿฌ ์„œํ‚ท์˜ ์กด์žฌ ์กฐ๊ฑด

  • ๊ฐ ์ •์ ์— ๋“ค์–ด์˜ค๋Š” ๊ฐ„์„ ์˜ ์ˆ˜์™€ ๋‚˜๊ฐ€๋Š” ๊ฐ„์„ ์˜ ์ˆ˜๊ฐ€ ๊ฐ™์•„์•ผ ํ•œ๋‹ค.

๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์—์„œ ์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ์˜ ์กด์žฌ ์กฐ๊ฑด

  • ์‹œ์ž‘์ ์ด a, ๋์ ์ด b์ผ ๋•Œ, a์—์„œ ๋‚˜๊ฐ€๋Š” ๊ฐ„์„ ์˜ ์ˆ˜ = ๋“ค์–ด์˜ค๋Š” ๊ฐ„์„ ์˜ ์ˆ˜ + 1 ์ด ๋˜์–ด์•ผํ•˜๊ณ , b์—์„œ๋Š” ๋“ค์–ด์˜ค๋Š” ๊ฐ„์„ ์˜ ์ˆ˜ = ๋‚˜๊ฐ€๋Š” ๊ฐ„์„ ์˜ ์ˆ˜ + 1์ด์–ด์•ผ ํ•œ๋‹ค.

๐ŸŒฑ ์˜ค์ผ๋Ÿฌ ์„œํ‚ท vs ์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ

๊ฐ ์ •์ ์˜ ์ฐจ์ˆ˜๋ฅผ ํ™•์ธํ•˜์ž!

โŒจ๏ธ ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์—์„œ ์˜ค์ผ๋Ÿฌ ์„œํ‚ท ํ˜น์€ ์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ ์ฐพ์•„๋‚ด๊ธฐ

getEulerCircuit : ์˜ค์ผ๋Ÿฌ ์„œํ‚ท ํ˜น์€ ํŠธ๋ ˆ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ ๊ณ„์‚ฐ

void getEulerCircuit(int here, vector<int>& circuit) {
  for(int there=0; there<adj.size(); ++there) { //๋ชจ๋“  ์ •์ ์— ๋Œ€ํ•ด
    while(adj[here][there] > 0) {//์—ฐ๊ฒฐ๋œ ์ •์ ์ด ์žˆ๋Š” ํ•œ
      adj[here][there]--; //<here-there> ๊ฐ„์„ ์€ ๊ฐํ•˜๊ณ 
      getEulerCircuit(there, circuit); //์—ฐ๊ฒฐ๋œ ์ •์ ์— ๋Œ€ํ•ด ํ•จ์ˆ˜์žฌ๊ท€ํ˜ธ์ถœ
    } 
  }
  circuit.push_back(here); //๊ฒฝ๋กœ์— ์ถ”๊ฐ€
}

getEulerTrailOrCircuit : ํ˜„์žฌ ๊ทธ๋ž˜ํ”„์˜ ์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ์ด๋‚˜ ์„œํ‚ท์„ ๋ฐ˜ํ™˜

vector<int> getEulerTrailOrCircuit() {
  vector<int> circuit;
  for(int i=0; i<26; ++i) { //๋ชจ๋“  ๋ฌธ์ž์ •์ ์— ๋Œ€ํ•ด 
    if(outdegree[i] == indegree[i] + 1) {//๋‚˜๊ฐ€๋Š” ๊ฐ„์„ ์ด ๋“ค์–ด์˜ค๋Š” ๊ฐ„์„ ๋ณด๋‹ค ํ•œ ๊ฐœ ๋” ๋งŽ์€ ๊ฒฝ์šฐ๋ผ๋ฉด, ์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ
      getEulerCircuit(i, circuut); //๊ฒฝ๋กœ๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค
      return circuit; //๊ณ„์‚ฐ๋œ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜
    }
  }
  for(int i=0; i<26; ++i) { //๋ชจ๋“  ๋ฌธ์ž ์ •์ ์— ๋Œ€ํ•ด
    if(outdegree[i]) { //์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ์ด ์•„๋‹ˆ๋ฉด ์˜ค์ผ๋Ÿฌ ์„œํ‚ท
      getEulerCircuit(i, circuit); //๊ฒฝ๋กœ๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค
      return circuit; //๊ณ„์‚ฐ๋œ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜
    }
  }
  return circuit; //๊ฒฝ๋กœ ๊ณ„์‚ฐ์— ์‹คํŒจํ–ˆ์œผ๋ฉด ๋นˆ ๋ฐฐ์—ด ๋ฐ˜ํ™˜
}

๐ŸŒฑ ์˜ค์ผ๋Ÿฌ ์„œํ‚ท/ํŠธ๋ ˆ์ผ์˜ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ

์กด์žฌ ์กฐ๊ฑด ํ™•์ธํ•˜๊ธฐ!

โŒจ๏ธ ๋๋ง์ž‡๊ธฐ ๋ฌธ์ œ๋ฅผ ์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ ๋ฌธ์ œ๋กœ ๋ฐ”๊ฟ” ํ•ด๊ฒฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

(= ์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ์ถœ๋ ฅ ๋ฌธ์ž์—ด์„ ๊ณ„์‚ฐํ•ด ๋ฐ˜ํ™˜ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜)

checkEuler() : ํ˜„์žฌ ๊ทธ๋ž˜ํ”„์˜ ์˜ค์ผ๋Ÿฌ ์„œํ‚ท/ํŠธ๋ ˆ์ผ ์กด์žฌ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜

solve() : ๊ฒฝ๋กœ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์ถœ๋ ฅํ•˜๋Š” ํ•จ์ˆ˜

๐Ÿ“ข **<์ฐธ๊ณ > ์ผ๋ถ€ ๋ณ€์ˆ˜๋ช…์„ ๋ฐ”๊พธ์—ˆ์œผ๋‚˜, ์ฝ”๋“œ๋‚ด์šฉ์€ ์ฑ…๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. **

bool checkEuler() {
  int startCnt = 0; //์˜ˆ๋น„์‹œ์ž‘์ ๊ฐœ์ˆ˜ ์นด์šดํŠธ
  int endPoint = 0; //์˜ˆ๋น„๋์ ๊ฐœ์ˆ˜ ์นด์šดํŠธ
  for(int i=0; i<26; ++i) {
    int diff = outdegree[i] - indegree[i];//์ž…์ถœ๊ฐ„์„  ๊ฐœ์ˆ˜์ฐจ์ด
    if(diff < -1 ||diff > 1) return false; //์ฐจ์ด๊ฐ€ +1์ดˆ๊ณผ, -1๋ฏธ๋งŒ์ด๋ฉด ์˜ค์ผ๋Ÿฌ ์„œํ‚ท/ํŠธ๋ ˆ์ผ ์•ˆ๋จ
    if(diff == 1) startCnt++; //๋‚˜๊ฐ€๋Š” ๊ฐ„์„ ์ด ๋” ๋งŽ์œผ๋ฉด ์˜ˆ๋น„์‹œ์ž‘์  ๊ฐœ์ˆ˜ +1
    if(diff == -1) endCnt++; //๋“ค์–ด์˜ค๋Š” ๊ฐ„์„ ์ด ๋” ๋งŽ์œผ๋ฉด ์˜ˆ๋น„๋์  ๊ฐœ์ˆ˜ +1
  }
  //์ด ๊ณ„์‚ฐ๋œ ์˜ˆ๋น„์‹œ์ž‘์ , ์˜ˆ๋น„๋์  ๊ฐœ์ˆ˜๊ฐ€ 1์ผ ๋•Œ(=์˜ค์ผ๋Ÿฌ ํŠธ๋ ˆ์ผ) ํ˜น์€
  //๋‘˜ ๋‹ค 0์ผ ๋•Œ(=์˜ค์ผ๋Ÿฌ ์„œํ‚ท)๋งŒ true๋ฐ˜ํ™˜
  return (startCnt==1 && endCnt==1) || (startCnt==0 && endCnt==0)
}
string solve(const vector<string>& words) {
  makeGraph(words); //๊ทธ๋ž˜ํ”„ ๋งŒ๋“ค๊ณ 
  if(!checkEuler()) return "IMPOSSIBLE"; //์˜ค์ผ๋Ÿฌ ์„œํ‚ท/ํŠธ๋ ˆ์ผ ์•„๋‹ˆ๋ฉด impossible๋ฐ˜ํ™˜
  //์•„๋‹ˆ๋ผ๋ฉด ์˜ค์ผ๋Ÿฌ ์„œํ‚ท์ด๋‚˜ ํŠธ๋ ˆ์ผ์ด๋ผ๋Š” ๊ฒƒ์ด๋ฏ€๋กœ
  vector<int> circuit = getEulerTrailOrCircuit(); //๊ณ„์‚ฐ๋œ ๊ฒฝ๋กœ๋ฅผ circuit์— ์ €์žฅ
  if(circuit.size() != words.size()+1) return "IMPOSSIBLE"; //๋ชจ๋“  ๊ฐ„์„ ์„ ๋ฐฉ๋ฌธํ–ˆ๋Š”์ง€ ํ™•์ธ
  //์—ฌ๊ธฐ๊นŒ์ง€์™”๋‹ค๋ฉด, ์ •์ƒ์ ์ธ ์˜ค์ผ๋Ÿฌ ์„œํ‚ท/ํŠธ๋ ˆ์ผ ๊ฒฝ๋กœ๋ผ๋Š” ๊ฒƒ์ด๋ฏ€๋กœ
  reverse(circuit.begin(), circuit.end()); //๊ฒฝ๋กœ ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟ”์ฃผ์–ด ์‹œ์ž‘์ ๋ถ€ํ„ฐ ๋์  ์ˆœ์„œ๋กœ ๋ฐฐ์—ดํ•ด์ฃผ๊ณ 
  string ret; //๋‹ต์œผ๋กœ ์ถœ๋ ฅํ•˜๊ฒŒ ๋  ๋ฌธ์ž์—ด ๋ณ€์ˆ˜ ์ƒ์„ฑ
  for(int i=0; i<circuit.size(); i++) {//๊ฒฝ๋กœ์˜ ์ •์  ์ˆ˜๋งŒํผ
    int a = circuit[i-1]; //์‹œ์ž‘์ 
    int b = circuit[i]; //๋์ 
    if(ret.size()) ret += " "; //์ •์  ์‚ฌ์ด์— ๊ณต๋ฐฑ๋ฌธ์ž์—ด ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ 
    ret += graph[a][b].pop_back(); //๋ฌธ์ž์—ด์— ์ •์  ์ €์žฅ
  }
  return ret; //๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
}

โฑTime Complexityโฑ

O(nA) : n์€ ๋‹จ์–ด์˜ ์ˆ˜, A๋Š” ์•ŒํŒŒ๋ฒณ์˜ ์ˆ˜