알고리즘/백준
[백준] 5670번 - 휴대폰 자판
래울
2024. 12. 22. 04:30
문제
https://www.acmicpc.net/problem/5670
풀이
Trie: https://doraeul19.tistory.com/415
전형적인 트라이 문제, 근데 입출력 형식이 여러개의 TC이므로 while(cin >> N)으로 입력받자
Insert함수를 구현해서 트리를 잘 만들어주고, Find함수에서 자판을 눌러야하는 횟수를 더해가면 된다.
자판을 눌러야 하는 경우
1. 맨 처음 글자: 첫 번째 글자는 무조건 눌러야 한다.
2. 다른 문자열과 구분되지 않는 경우
- 현재 문자가 isEnd(다른 문자열의 끝인 경우)
- 다음 문자로 올 수 있는 경우가 2개 이상인 경우
코드
#include <vector>
#include <cstring>
#include <queue>
#include <iostream>
#include <algorithm>
#include <stack>
#include <string>
#include <unordered_map>
#include <map>
#include <cmath>
using namespace std;
int T;
int N;
string arr[100000];
double s = 0;
struct Trie {
int isEnd;
Trie* child[26];
int childCnt;
Trie() {
isEnd = 0;
childCnt = 0;
for (int i = 0; i < 26; ++i) child[i] = NULL;
}
~Trie() {
for (int i = 0; i < 26; ++i) delete child[i];
}
void Insert(string& str, int index)
{
if (index == str.size()) {
isEnd = 1;
return;
}
int ch = str[index] - 'a';
if (child[ch] == NULL) {
childCnt++;
child[ch] = new Trie();
}
child[ch]->Insert(str, index + 1);
}
int Find(string& str, int index, int cnt)
{
if (index == str.size()) {
s += cnt;
return isEnd;
}
int ch = str[index] - 'a';
if (child[ch] == NULL) return 0;
else {
if (index == 0 || isEnd || childCnt > 1) return child[ch]->Find(str, index + 1, cnt + 1);
else return child[ch]->Find(str, index + 1, cnt);
}
}
};
void solve()
{
Trie root;
string inp;
for (int i = 0; i < N; ++i) {
cin >> arr[i];
root.Insert(arr[i], 0);
}
s = (double)0.0;
for (int i = 0; i < N; ++i) {
root.Find(arr[i], 0, 0);
}
double ret = round((s / (double)N) * 100.0) / 100.0;
cout << ret <<"\n";
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cout.precision(2);
cout << fixed;
while (cin >> N) solve();
return 0;
}