티스토리 뷰
백준 온라인 저지(BOJ) 20920번 영단어 암기는 괴로워
https://www.acmicpc.net/problem/20920
20920번: 영단어 암기는 괴로워
첫째 줄에는 영어 지문에 나오는 단어의 개수 $N$과 외울 단어의 길이 기준이 되는 $M$이 공백으로 구분되어 주어진다. ($1 \leq N \leq 100\,000$, $1 \leq M \leq 10$) 둘째 줄부터 $N+1$번째 줄까지 외울 단
www.acmicpc.net
* 사용언어 : C언어, C++
1. 문제
효율적인 영어 단어 암기를 위한 아래의 정렬 규칙에 따라 단어를 정렬한 후 순서대로 출력
1) 자주 나오는 단어 → 2) 길이가 긴 단어 → 3) 알파벳 순서
2. 풀이
Hash Table 자료 구조와 Merge Sort 정렬 알고리즘을 사용하여 풀었습니다.
단어가 나온 빈도수를 확인하기 위해서 단어를 key로 하는 Hash Table로 구현했고,
단어가 등장할 때마다 hash 탐색 후 없으면 추가해주고 hash의 value 중 하나인 cnt 값을 증가시켰습니다.
길이가 M 미만인 단어는 출력 대상이 아니므로 hash에 기록조차 하지 않습니다.
기록을 마친 후에는 기록이 된 hash 구조체들만 추려내어 하나의 배열로 정리합니다.
그리고 그 배열을 문제의 규칙에 따라 정렬한 뒤 순서대로 출력하면 됩니다.
hash 구조체를 추려내는 과정에서 메모리 사용을 최소화하기 위해
구조체 자체가 아닌 구조체의 주소값, 즉 포인터를 배열로 만들었습니다.
c언어에서 주소값은 크기가 4 byte 뿐이라 상대적으로 공간 효율이 좋아지는데,
정렬 시 swap을 할 때에도 값 하나만 바꾸면 되기 때문에 시간 효율까지 좋아집니다.
구조체를 활용한 정렬 문제에서는 포인터를 쓰지 않을 이유가 없으니 숙달한 후 자주 활용하기를 권장드립니다.
3. 코드
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
/*
20920_영단어 암기는 괴로워
5608KB 64ms
*/
#include <cstdio>
const int LM = 100000;
const int HLM = LM * 3 / 2;
const int CLM = 11;
int N, M, slen, wCnt;
char s[CLM];
struct _hash {
char key[CLM];
int cnt;
int len;
} HASH[HLM];
_hash *a[LM], *t[LM];
int strlen(const char *a) {
int len = 0;
while (*a++) ++len;
return len;
}
int strcmp(const char *a, const char *b) {
while (*a && *b && *a == *b) *a++, *b++;
return *a - *b;
}
void strcpy(const char *src, char *des) {
while (*src) *des++ = *src++;
*des = 0;
}
int hash(char *key) {
unsigned long long hash = 5381;
int c;
while (c = *key++) hash = (((hash << 5) + hash) + c) % HLM;
return hash;
}
int h_find(char *key) {
int h = hash(key);
int cnt = HLM;
while (HASH[h].key[0] && cnt--) {
if (!strcmp(HASH[h].key, key)) return h;
h = (h + 1) % HLM;
}
return h;
}
int hashcmp(_hash *a, _hash *b) {
if (a->cnt != b->cnt) return b->cnt - a->cnt;
if (a->len != b->len) return b->len - a->len;
return strcmp(a->key, b->key);
}
void mSort(int s, int e) {
if (s >= e) return;
int m = (s + e) / 2;
mSort(s, m);
mSort(m + 1, e);
int i = s, j = m + 1, k = s;
while (i <= m && j <= e) {
if (hashcmp(a[i], a[j]) < 0) t[k++] = a[i++];
else t[k++] = a[j++];
}
while (i <= m) t[k++] = a[i++];
while (j <= e) t[k++] = a[j++];
for (i = s; i <= e; ++i) a[i] = t[i];
}
int main() {
#ifdef _WIN32
freopen("input.txt", "r", stdin);
#endif // _WIN32
scanf("%d %d", &N, &M);
for (int i = 0; i < N; ++i) {
scanf("%s", s);
slen = strlen(s);
if (slen < M) continue;
int h = h_find(s);
_hash *hash = &HASH[h];
if (!hash->key[0]) {
strcpy(s, hash->key);
hash->len = slen;
}
++hash->cnt;
}
for (int i = 0; i < HLM; ++i) {
if (!HASH[i].key[0]) continue;
a[wCnt++] = &HASH[i];
}
mSort(0, wCnt - 1);
for (int i = 0; i < wCnt; ++i) printf("%s\n", a[i]->key);
return 0;
}
'개발자 > 문제풀이 (C언어)' 카테고리의 다른 글
[백준/BOJ] 10870번 피보나치 수 5 (C/C++) (0) | 2024.01.07 |
---|---|
[백준/BOJ] 27433번 팩토리얼 2 (C/C++) (0) | 2024.01.06 |
[백준/BOJ] 2108번 통계학 (C/C++) (0) | 2024.01.02 |
[백준/BOJ] 26069번 붙임성 좋은 총총이 (C/C++) (0) | 2024.01.01 |
[백준/BOJ] 25192번 인사성 밝은 곰곰이 (C/C++) (0) | 2023.12.27 |
- Total
- Today
- Yesterday
- 센터독서클럽
- 자료구조
- 호암의마지막꿈
- 나는늘잘해야한다고생각한다
- 독서감상평
- 여가포인트
- 문현공
- 동탄에듀센터2
- 시대예보
- 긴 자리 덧셈 뺄셈
- 안전운전특약
- 인간본성불패의법칙
- 동탄에듀센터
- 당신도느리게나이들수있습니다
- 나의첫죽음학수업
- 독서 감상평
- 최재천의공부
- 세상을 읽는 새로운 언어 빅데이터
- 유연함의힘
- 정올
- 영화감상평
- 긴 자리 곱셈
- AdSendse
- 알고리즘
- 자동차보험
- 쿠프마케팅
- 정세현의통찰
- 관계가상처가되기전에
- JUNGOL
- 삼성전자
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |