문제 링크: https://www.acmicpc.net/problem/5052

 

여러 풀이가 있겠는데, 트라이(trie)로 풀 수 있습니다.

일단 트라이를 쭉 완성합니다. 문자열갖고 트라이를 만들 때 문자열의 끝부분에 해당되는 노드마다 끝부분이라고 체크를 해줍니다.

그 다음, dfs로 트라이를 한번 쭉 순회를 하는데 끝부분이라고 체크가 되어 있으면서 자식 노드가 있는 노드가 있으면 일관성이 없게 됩니다.

 

트라이를 배열로 구현해서 풀었습니다. 동적할당은 귀찮네요.

트라이 관련 내용은 나중에 게시물로 정리해서 올릴 예정입니다.

#include <bits/stdc++.h>
using namespace std;

int trie[100001][10];
bool terminating[100001];
int trie_size;

void trie_insert(const string& s) {
	auto sz = s.size();
	assert(sz <= 10);

	int node = 0;
	for (auto& c : s) {
		if (trie[node][c - '0'] == 0) {
			trie[node][c - '0'] = ++trie_size;
			node = trie_size;
		}
		else
			node = trie[node][c - '0'];
	}

	terminating[node] = true;
}

bool consistent(int node) {
	if (terminating[node] && accumulate(trie[node], trie[node]+10, 0) != 0)
		return false;

	bool ret = true;
	for (int i=0; i<10; ++i)
		if (trie[node][i])
			ret &= consistent(trie[node][i]);

	return ret;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr), cout.tie(nullptr);
	
	int t;
	cin >> t;
	while (t--) {
		memset(trie, 0, sizeof(trie));
		memset(terminating, 0, sizeof(terminating));
		trie_size = 0;

		int n;
		cin >> n;

		string s;
		while (n--) {
			cin >> s;
			trie_insert(s);
		}

		cout << (consistent(0) ? "YES\n" : "NO\n");
	}
	
	return 0;
}

위에서 설명한대로 짠 버전입니다.

 

 

#include <bits/stdc++.h>
using namespace std;

int trie[100001][10];
int trie_size;
bool consistency;

void trie_insert(const string& s) {
	auto sz = s.size();
	assert(sz <= 10);

	int node = 0;
	for (auto& c : s) {
		if (trie[node][c - '0'] == 0) {
			trie[node][c - '0'] = ++trie_size;
			node = trie_size;
		}
		else
			node = trie[node][c - '0'];
	}

	int next_cnt = 0;
	for (int i = 0; i < 10; ++i)
		next_cnt += (trie[node][i] != 0);

	if (next_cnt)
		consistency = false;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr), cout.tie(nullptr);
	
	int t;
	cin >> t;
	while (t--) {
		memset(trie, 0, sizeof(trie));
		consistency = true;
		trie_size = 0;

		int n;
		cin >> n;
		vector<string> vs(n);
		for (auto& s : vs)
			cin >> s;
		// 길이순 정렬 (내림차순)
		sort(vs.begin(), vs.end(), [](string& s1, string& s2){return s1.size() > s2.size();});

		for (auto& s : vs)
			trie_insert(s);

		cout << (consistency ? "YES\n" : "NO\n");
	}
	
	return 0;
}

배열로 구현한 트라이 쓴 건 같은데, 전화번호를 다 입력받고 길이 내림차순으로 정렬한 뒤 트라이를 만들면서 일관성 여부를 체크한 버전입니다.

원래 이 버전을 짠 다음에 문자열 정렬을 굳이 안해도 될 것 같아서 위에 버전으로 다시 짰는데, 밑에 버전이 더 빠르네요?

재귀를 안써서 그런가.. 뭐 모르겠습니다.

반응형

'Online Judge > 백준' 카테고리의 다른 글

[백준][C++] 14425: 문자열 집합  (0) 2020.07.16
[백준][C++] 14725: 개미굴  (0) 2020.07.16
[백준][C++] 14582: 오늘도 졌다  (0) 2020.07.16
[백준][C++] 11946: ACM-ICPC  (0) 2020.07.16
[백준][C++] 11947: 이런 반전이  (0) 2020.07.16