문제 : https://www.acmicpc.net/problem/5670
트라이 Trie
자료구조 트라이를 이용하는 문제입니다.
1) 들어오는 모든 문자열을 insert 해서 트라이를 만듭니다.
2) 문자열을 하나씩 트라이에서 탐색을 수행합니다.
2-1) 현재 첫 번째 글자라면 무조건 버튼을 눌러야 하므로 다음 글자로 넘어가며 카운트를 증가합니다.
2-2) 현재 글자에서 다음 글자로 가는 길이 2가지 이상이거나 혹은 현재 글자에서 끝난 문자열이 있다면 버튼을 눌러야 하므로 다음 글자로 넘어가며 카운트를 증가합니다.
2-3) 위의 경우가 아니라면 자동으로 입력되므로 카운트를 증가시키지 않고 다음 글자로 탐색을 진행합니다.
알고리즘은 위와 같이 간단합니다. 하지만, EOF가 입력될 때까지 매번 트라이를 구현해야하는 문제로, delete 를 하지 않는다면 메모리 초과가 발생합니다.
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
struct Trie {
bool finish; //끝나는 지점을 표시해줌
Trie* next[26]; //26가지 알파벳에 대한 트라이
Trie() {
finish = false;
memset(next, 0, sizeof(next));
}
~Trie() {
for (int i = 0; i < 26; i++)
if (next[i])
delete next[i];
}
void insert(const char* key) {
if (*key == '\0')
finish = true; //문자열이 끝나는 지점일 경우 표시
else {
int curr = *key - 'a';
if (next[curr] == NULL)
next[curr] = new Trie(); //탐색이 처음되는 지점일 경우 동적할당
next[curr]->insert(key + 1); //다음 문자 삽입
}
}
int find(const char* key, int cnt) {
if (*key == '\0')
return cnt;
if (cnt == 0)
return next[*key - 'a']->find(key + 1, cnt + 1);
int check = 0;
for (int i = 0; i < 26; i++)
if (next[i] != NULL)
check++;
if (check > 1 || finish) // 가는 길이 2가지 이상
cnt++;
return next[*key - 'a']->find(key + 1, cnt);
}
};
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
while (1) {
int N;
cin >> N;
if (cin.eof())
break;
Trie* trie = new Trie();
vector<string> list(N);
for (int i = 0; i < N; i++){
cin >> list[i];
trie->insert(list[i].c_str());
}
int total = 0;
for (int i = 0; i < N; i++)
total += trie->find(list[i].c_str(), 0);
cout << fixed;
cout.precision(2);
cout << double(total) / double(N) << '\n';
delete trie;
}
return 0;
}
'Problem Solving > BOJ' 카테고리의 다른 글
[BOJ] 9370 : Destination Unknown (0) | 2020.04.29 |
---|---|
[BOJ] 1744 : 수 묶기 - travelbeeee (0) | 2020.04.24 |
[BOJ] 5052 : Phone List (0) | 2020.04.22 |
[BOJ] 2458 : 키 순서 - travelbeeee (0) | 2020.04.14 |
[BOJ] 16933 : 벽 부수고 이동하기 3 - travelbeeee (0) | 2020.04.13 |