Baekjoon/Platinum

C++ / 백준 / 19585 / 전설

GitHubSeob 2023. 8. 27. 18:33
문제

 

https://www.acmicpc.net/problem/19585

 

19585번: 전설

Sogang ICPC Team에는 색상 이름과 닉네임의 순서로 이여서 팀명을 지으면 ICPC 리저널에서 수상할 수 있다는 전설이 있다. 색상 이름들과 닉네임들이 주어질 때, Q개의 팀에 대해 다음 리저널에서 수

www.acmicpc.net

문제풀이

 

색상은 트라이, 닉네임은 set을 이용해 풀었다.

처음에는 둘 다 해시로 풀어서 안되길래 라빈카프로 바꿔서 풀어봤는데도 안 됐다.

그래서 트라이 + 해시로 풀어봤는데 15%에서 계속 틀리길래 검색을 해봤는데 반례가 하나도 없길래 직접 생각해 봤다.

 

처음에는 트라이로 검색해 나가면서 isEnd가 true이면 break를 통해 색상은 더 이상 찾지 않고 나머지 문자열이 닉네임에 있는지 판별을 하는 식으로 했다.

하지만 색상이 red, re, r 이렇게 있고 닉네임이 shift일 때

redshift, reshift는 No가 출력되는 반례가 있었다.

그래서 현재 문자가 어떤 색상의 끝일 때 나머지 문자열이 닉네임에 없을 때, 다시 다음 색상을 찾는 과정을 하도록 했다.

 

Color* ptr;

int Color::search(char& c) {
	if (ptr->child.find(c) == ptr->child.end()) return -1;
	else {
		if (ptr->child[c]->isEnd == true) {
			ptr = ptr->child[c];
			return 1;
		}
		else {
			ptr = ptr->child[c];
			return 0;
		}
	}
}

ptr을 전역변수로 두고 문자를 하나하나씩 보면서 색상에 해당 문자가 없으면 -1을,

해당 문자가 색상의 끝이면 1을,

해당 문자가 끝이 아니면 0을 return 하도록 했다.

-1이 return 되면 NO를 출력하면 되고, 1이 return 되면 나머지 문자열에 대해 닉네임이 있는지를 판별하면 된다.

0을 return 하는 경우는 다음 문자를 계속 탐색하라는 의미이다.

 

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

struct Color {
	map<char, Color*> child;
	bool isEnd;

	Color() : child(), isEnd(false) {}
	~Color() {
		child.clear();
	}

	void insert(string& str) {
		Color* color = this;
		for (int idx = 0; idx < str.size(); ++idx) {
			if (color->child.find(str[idx]) == color->child.end()) {
				color->child[str[idx]] = new Color();
			}
			color = color->child[str[idx]];
			if (idx + 1 == str.size()) color->isEnd = true;
		}
	}
	int search(char& c);
};

Color* ptr;

int Color::search(char& c) {
	if (ptr->child.find(c) == ptr->child.end()) return -1;
	else {
		if (ptr->child[c]->isEnd == true) {
			ptr = ptr->child[c];
			return 1;
		}
		else {
			ptr = ptr->child[c];
			return 0;
		}
	}
}

unordered_set<string>names;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);

	int C(0), N(0);
	cin >> C >> N;

	Color* color = new Color();
	string input("");
	for (int idx = 0; idx < C; ++idx) {
		cin >> input;
		color->insert(input);
	}
	for (int idx = 0; idx < N; ++idx) {
		cin >> input;
		names.insert(input);
	}

	int Q(0), ret(0);
	cin >> Q;

	for (int idx = 0; idx < Q; ++idx) {
		cin >> input;
		ptr = color;
		bool flag(false);
		for (int idx2 = 0; idx2 < input.size(); ++idx2) {
			ret = color->search(input[idx2]);
			if (ret == 1) {
				string name = input.substr(idx2 + 1);
				if (names.find(name) != names.end()) {
					flag = true;
					break;
				}
			}
			else if (ret == -1) {
				break;
			}
		}
		if (flag == true) cout << "Yes\n";
		else cout << "No\n";
	}
}