본문 바로가기

알고리즘

[2018 KAKAO BLIND RECRUITMENT] [3차] 자동완성

https://programmers.co.kr/learn/courses/30/lessons/17685

 

코딩테스트 연습 - [3차] 자동완성 | 프로그래머스

자동완성 포털 다음에서 검색어 자동완성 기능을 넣고 싶은 라이언은 한 번 입력된 문자열을 학습해서 다음 입력 때 활용하고 싶어 졌다. 예를 들어, go 가 한 번 입력되었다면, 다음 사용자는 g 만 입력해도 go를 추천해주므로 o를 입력할 필요가 없어진다! 단, 학습에 사용된 단어들 중 앞부분이 같은 경우에는 어쩔 수 없이 다른 문자가 나올 때까지 입력을 해야 한다. 효과가 얼마나 좋을지 알고 싶은 라이언은 학습된 단어들을 찾을 때 몇 글자를 입력해야 하

programmers.co.kr

 

 

 

이 문제는 Trie 자료 구조를 사용해서 풀어야 한다.

Trie 자료 구조가 익숙치 않으신 분들은, 다음 글을 참고하시길 바란다.

 

 

 


https://real-012.tistory.com/41?category=769031

 

Trie(트라이) 자료구조 정의, 예제 코드

2020 신입 개발자 카카오 블라인드 시험을 치다가, 문자열 처리에 대한 자료구조를 알게 되었다. Trie 자료구조에 대한 다음과 같은 모습으로 생겼다. 위에 보면, APPLE, LABLE, CABLE이라는 단어를 넣은 것이다...

real-012.tistory.com

 

 

 

문제를 이해하다 보면, Trie 자료구조가 필요하다고 느낄 것이다. 다른 방법으로도 풀 수 있겠지만, 이 문제는 Trie 자료구조가 가장 적당하고 빠를 것이다. 다른 방식의 풀이는 최소한 N * N의 시간복잡도가 필요할 것으로 예상된다.

 

 

 

 

Trie 자료구조를 이용하면 문제는 간단해진다. 이 문제를 풀기 위해서는, cnt, Trie* 2가지 변수가 있으면 충분하다. 

 

 

 

cnt = 해당 문자의 출현 횟수 및 종료 역할

Trie* = Trie형의 다음 문자 주소값(a - z)

 

 

 

 

insert 함수가 동작하면서, Trie 자료구조가 완성될 것이다. 두 문자열이 있을 때, 중복되는 문자들은 모두 들어가야 하므로 정답에 더해져야한다. 따라서, cnt > 1인 경우를 찾아야 한다. 또한, 처음 cnt == 1인 순간에도 신경을 써야한다.

 

 

 

 

gone의 경우에는 'n'은 cnt가 1이지만, 구분하기 위해서 gon까지 입력을 하므로, 처음으로 cnt가 1이 되는 순간까지만 정답의 문자 개수에 포함시켜주면 된다.

 

 

 


 

 

 

해설코드(C++).

 

 

 

#include <string>

#include <vector>

#include <iostream>

#include <algorithm>

#include <cstring>

 

using namespace std;

 

int result = 0;

 

struct Trie {

    bool finish = false;

    int cnt = 0;

    Trie* next[26];

    Trie() : finish(false) {

        memset(next, 0sizeof(next));

    }

 

    void insert(const char* key) {

        if ((*key) == '\0') {

            if (cnt == 1) {

                finish = true;

            }

            return;

        }

 

        int curr = (*key) - 'a';

        if (!next[curr]) {

            next[curr] = new Trie();

        }

        next[curr]->cnt += 1;

        next[curr]->finish = false;

        next[curr]->insert(key + 1);

    }

 

    void count() {

        if (cnt > 1)

            result += cnt;

        else if (cnt == 1) {

            result += 1;

            return;

        }

 

        if (finish) {

            return;

        }

 

        for (int i = 0; i < 26; i++)

        {

            if (next[i])

                next[i]->count();

        }

    }

};

 

int solution(vector<string> words) {

    Trie* trie = new Trie();

    for (int i = 0; i < words.size(); i++) {

        trie->insert(words[i].c_str());

    }

    trie->count();

 

 

    return result;

}

 

int main(void) {

    solution({ "go","gone","guild" });

}