본문 바로가기

알고리즘/백준 문제풀이

[BOJ 5670] 휴대폰 자판

반응형

 

[문제]

 

www.acmicpc.net/problem/5670

 

5670번: 휴대폰 자판

휴대폰에서 길이가 P인 영단어를 입력하려면 버튼을 P번 눌러야 한다. 그러나 시스템프로그래밍 연구실에 근무하는 승혁연구원은 사전을 사용해 이 입력을 더 빨리 할 수 있는 자판 모듈을 개발

www.acmicpc.net

 

[난이도] 

 

- Platinum III (solved.ac 20.12.13 기준)

 

 

[필요 개념]

 

- 트라이 (Trie)

 

 

[풀이]

 

자동 입력이 되는 순간은 현재 노드에서 끝나는 문자열이 없으면서, 자식 노드가 하나밖에 없는 경우이다.

따라서 트라이를 생성할 때 자식의 수를 저장해두고, 문자열을 탐색할 때 자식의 수가 둘 이상이거나,

현재 노드에서 끝나는 다른 문자열이 있고 자식의 수가 1이면 버튼을 눌러줘야 하기 때문에 +1을 해서 다음 노드로 넘겨준다.

문자열의 끝에 도달하면 지금까지 더해온 값을 ans에 추가해준다.  

 

 

[소스 코드]

 

#include<bits/stdc++.h>
#define sz(x) (int)x.size()
using namespace std;
int ans;
struct Trie {
	Trie *ch[26];
	int cnt;
	bool end;
	Trie() {
		for (int i = 0; i < 26; i++) ch[i] = NULL;
		cnt = 0;
		end = false;
	}
	~Trie() {
		for (int i = 0; i < 26; i++) if (ch[i]) delete ch[i];
	}
	void insert(const char* s) {
		if (!*s) {
			end = true;
			return;
		}
		int now = *s - 'a';
		if (!ch[now]) {
			ch[now] = new Trie;
			cnt++;
		}
		ch[now]->insert(s + 1);
	}
	void find(const char *s, int k, bool root) {
		if (!*s) {
			ans += k;
			return;
		}
		int now = *s - 'a';
		if (root) ch[now]->find(s + 1, k, false);
		else {
			if (cnt == 1 && !end) ch[now]->find(s + 1, k, false);
			else ch[now]->find(s + 1, k + 1, false);
		}
	}
};
int main(void) {
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	int n;
	while (cin>>n) {
		Trie *root = new Trie;
		ans = 0;
		vector<string> v;
		for (int i = 1; i <= n; i++) {
			string s; cin >> s;
			v.push_back(s);
			root->insert(s.c_str());
		}

		for (string s : v) {
			root->find(s.c_str(), 1, true);
		}
		cout << fixed;
		cout.precision(2);
		cout << (double)ans / sz(v) << '\n';
		delete root;
	}
}

 

PC로 보시는 것을 권장합니다. 

피드백은 언제나 환영입니다. 댓글로 달아주세요 ^-^

반응형

'알고리즘 > 백준 문제풀이' 카테고리의 다른 글

[BOJ 7812] 중앙 트리  (2) 2020.12.14
[BOJ 9202] Boggle  (0) 2020.12.13
[BOJ 2809] 아스키 거리  (0) 2020.12.11
[BOJ 10256] 돌연변이  (0) 2020.12.11
[BOJ 9250] 문자열 집합 판별  (0) 2020.12.11