Trie

Trie 자료구조 이해하기

[5670 휴대폰 자판] https://www.acmicpc.net/problem/5670 .
트라이 자료구조를 이용한다.

문제상황 파악하기.

휴대폰의 자동완성 기능을 사용했을 때 버튼 누르는 횟수를 계산하는 문제이다.
트라이 자료구조를 이용하여 버튼을 누를 때마다 카운트를 해주면 된다.

Trie가 뭐길래?

트라이 자료구조는 원래 있던 문자면 따라가다가 달라지면 방향을 틀어 새로운 길을 만드는 트리구조이다.
생각하기는 편한 자료구조인데 처음보면은 구현은 어떻게 해야하지 싶다.
기본적으로는 연결리스트의 아이디어이다.
최적화할 때 맵을 이용하는 방법도 있지만 여기서는 알파벳 26개의 배열을 만들어서 트라이를 구현해보자!

아이디어 얻기.

트라이 구조를 만들고 단어가 끝날 때마다 bool형 isEnd에다가 체크를 했다.
그리고 그 단어들을 따라가며 isEnd가 나올 때마다 카운트를 해준다.
그러면 카운트된 수가 문자들을 치기 위해서 타이핑해야하는 숫자이고 이를 문자의 수로 나눠주면 평균이 된다.
이는 문자를 따라가며 단 한번만 수행 되므로 문자의 길이 즉, O(N)의 시간복잡도를 가질 것이다.
다만 알파벳이 새로 생길 때마다 공간을 할당하다보니 메모리의 소모가 크다.

주의할 점

동적할당을 했으면 delete를 이용하여 메모리를 비워야한다.

실제 코드

나머지 주의 할 점은 코드에 주석으로 처리했다.

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define fast_io cin.tie(NULL); cout.tie(NULL); ios_base::sync_with_stdio(false);
using namespace std;
typedef long long ll;


const int ALPHABET = 26;

struct Trie{
    Trie *children[ALPHABET];
    bool isEnd;
    Trie(){
        isEnd = false;
        for(int i=0;i<ALPHABET;i++) children[i] = NULL;
    }
    ~Trie(){
        for(int i=0;i<ALPHABET;i++)
            if(children[i]) delete children[i];
    }
};

void insert(Trie* root, string& key, bool isFirst, int idx){
    Trie *pCrawl = root;

    if(!pCrawl->children[key[idx]-'a']) {
        pCrawl->children[key[idx]-'a'] = new Trie();
        if(!isFirst){
            pCrawl -> isEnd = true; //처음으로 갈라지거나 끝나는 부분을 체크했음
            isFirst = true;
        }
    }
    if(idx==key.length()) {
        pCrawl -> isEnd = true;
        return;
    }
    insert(pCrawl->children[key[idx]-'a'], key, isFirst, idx+1);

}

int search(Trie* root, string& key){
    Trie * pCrawl = root;
    int ret = 0;
    for(int i=0;i<key.length();i++){
        int idx = key[i]-'a';
        if(pCrawl->isEnd) ret++;
        pCrawl = pCrawl->children[idx];
    }
    return ret;
}

vector<string> strs;

int main(){
    fast_io;
    int num;
    while (cin>>num){
        strs = vector<string> (num);
        Trie* root = new Trie();
        for(int i=0;i<num;i++){
            cin >> strs[i];
            insert(root, strs[i], false, 0);
        }
        int res = 0;
        for(int i=0;i<num;i++){
            res += search(root, strs[i]);
        }
        cout << fixed;
        cout.precision(2);
        cout << (double)res/(double)num << '\n';
        delete root;
    }
    
}

Leave a comment

2024

D&C Optimization

3 minute read

분할정복을 이용한 다이나믹 프로그래밍 최적화

Back to top ↑

2023

Back to top ↑

2022

Greedy

2 minute read

백준 18186번 라면사기(large) 문제풀이

SCC

1 minute read

백준 4196번 도미노 문제풀이

LCA

2 minute read

백준 3176번 도로 네트워크 문제풀이

2-SAT

1 minute read

백준 16367번 TV Show Game 문제풀이

Hashing

2 minute read

백준 21162번 뒤집기 K 문제풀이

Tree DP

1 minute read

백준 1949번 우수 마을 문제풀이

Trie

1 minute read

Trie 자료구조 이해하기

Merge Sort

1 minute read

merge sort를 이용하여 inversion 개수세기

Segment Tree

2 minute read

백준 11505 구간 곱 구하기 문제풀이

BFS

1 minute read

백준 2206 벽 부수고 이동하기 문제풀이

기하

1 minute read

백준 2166 다각형의 면적 문제풀이

이분탐색

1 minute read

백준 12015 가장 긴 증가하는 부분 수열2 문제풀이

누적 합

1 minute read

백준 10986 나머지합 문제풀이

Stack

1 minute read

스택 구현하기 ========== 자료구조의 기본이라고 하면 스택 과 큐가 있다 백준 10828번에서 마주친 스택

정렬1

1 minute read

매우매우 많은 정렬이 있지만 그중 가장 안 어려운 3가지를 공부해보았다.

Back to top ↑