알고리즘/백준

1764 듣보잡(라이브러리 사용x)

아메숑 2019. 11. 10. 20:31

1. 문제

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

 

1764번: 듣보잡

첫째 줄에 듣도 못한 사람의 수 N, 보도 못한 사람의 수 M이 주어진다. 이어서 둘째 줄부터 N개의 줄에 걸쳐 듣도 못한 사람의 이름과, N+2째 줄부터 보도 못한 사람의 이름이 순서대로 주어진다. 이름은 띄어쓰기 없이 영어 소문자로만 이루어지며, 그 길이는 20 이하이다. N, M은 500,000 이하의 자연수이다.

www.acmicpc.net

 

2. 코드

#include <iostream>

using namespace std;

const int HASH_SIZE = 200000;
struct Hash {
	char name[500000][21];
	int table[200000][30];
	int PN = 65534;
	int hash_size;

	unsigned int get_key(char* s) {
		unsigned int key = 0, p = 1;
		for (int i = 0; s[i] != 0; i++) {
			key += s[i] * p;
			p *= PN;
		}
		return key % HASH_SIZE;
	}

	void push(char *s) {
		for (int i = 0; s[i] != 0; i++) {
			name[hash_size][i] = s[i];
		}

		unsigned int key = get_key(s);
		int &size = table[key][0];
		table[key][++size] = hash_size;
		hash_size++;
	}

	int my_strcmp(char *a, char *b) {
		int i = 0;
		while (a[i]) {
			if (a[i] != b[i]) break;
			i++;
		}
		return a[i] - b[i];
	}

	int contain(char *s) {
		unsigned int key = get_key(s);
		int size = table[key][0];
		for (int i = 1; i <= size; i++) {
			int npos = table[key][i];
			if (my_strcmp(name[npos], s) == 0) return npos;
		}
		return -1;
	}

}map;

struct Store {
	char s[21];

	bool operator < (Store a) const {
		int idx = 0;
		while (s[idx]) {
			if (s[idx] != a.s[idx]) break;
			idx++;
		}
		return s[idx] < a.s[idx];
	}
}store[500000];

Store buf[500000];

void merge_sort(Store *s, int len) {
	if (len < 2) return;
	int mid = len / 2;
	int k = 0, i = 0, j = mid;
	merge_sort(s, mid);
	merge_sort(s + mid, len - mid);

	while (i < mid && j < len) {
		if (s[i] < s[j]) buf[k++] = s[i++];
		else buf[k++] = s[j++];
	}
	while(i<mid) buf[k++] = s[i++];
	while(j<len) buf[k++] = s[j++];
	for (int i = 0; i < len; i++) s[i] = buf[i];
}

int main() {

	ios::sync_with_stdio(false); cin.tie(0);
	int n, m;
	cin >> n >> m;

	char str[21];
	while (n--) {
		cin >> str;
		map.push(str);
	}
	int cnt = 0;
	while (m--) {
		cin >> str;
		if (map.contain(str) >= 0) {
			int idx = 0;
			while (str[idx]) {
				store[cnt].s[idx] = str[idx];
				idx++;
			}
			cnt++;
		}
	}

	merge_sort(store, cnt);

	cout << cnt << endl;
	for (int i = 0; i < cnt; i++) {
		cout << store[i].s << endl;
	}
}

 

3. 후기

우선 라이브러리를 사용하지 않고 풀기로 했기 때문에 map을 직접 구현하였다. 듣도 보도 못한 사람을 구하는 건 map을 사용해서 간단하게 구할 수 있었는데 사전순으로 정렬하는 부분은 좀 까다로웠다. 그래서 연산자 오버로딩을 이용해서 구현했다.