본문 바로가기
C, C++/Problem Solving

[백준BOJ 1157번] 단어 공부 해설

by hseoy 2020. 11. 23.
반응형

[문제 내용]

아래 링크로 설명을 대신한다.

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

 

1157번: 단어 공부

알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.

www.acmicpc.net

[해답 코드 및 설명]

#include <stdio.h>
#include <string.h>

int main(void) 
{
	int cnt[26] = {0, };
	char s[1000001] = {0, };
	
	scanf("%s", s);
	
	int len = strlen(s);
	for (int i = 0; i < len; i++) {
		if (s[i] >= 'a' && s[i] <= 'z') s[i] -= 'a' - 'A';
		cnt[s[i] - 'A'] ++;
	}
	
	int max_i = 0;
	for (int i = 0; i < 26; i++) {
		if (cnt[max_i] < cnt[i]) {
			max_i = i;
		}
	}
	
	int check = 0;
	for (int i = 0; i < 26; i++) {
		if (cnt[max_i] == cnt[i]) check++;
	}
	
	if (check == 1) printf("%c\n", max_i + 'A');
	else printf("?\n");
	
	return 0;
}

 이 문제는 크게 3개 부분으로 나눌 수 있다. 1. 알파벳의 개수를 카운팅하는 부분 2. 가장 많은 알파벳 구하기 3. 가장 많은 알파벳의 중복 체크.

int len = strlen(s);
for (int i = 0; i < len; i++) {
    if (s[i] >= 'a' && s[i] <= 'z') s[i] -= 'a' - 'A';
    cnt[s[i] - 'A'] ++;
}

위에서는 입력받은 문자열을 반복하면서 소문자이면 대문자로 변환해서 cnt[s[i] - 'A']++를 통해 카운팅 작업을 수행하고 있다. 여기서 실수하기 쉬운 것이 for 문의 조건에 strlen(s)을 그대로 넣는 것이다. 문자열의 길이가 짧으면 인식을 못할 수 있는 데 조건을 검사할 때마다 strlen작업을 수행하기에 문자열이 길어지면 시간초과가 나서 논리는 맞지만 답은 틀린 그러한 상황이 생길 수 있다. 그러므로 번거롭더라도 len이라는 새로운 변수를 만들어 strlen()의 결과를 저장해두고 사용하는 게 좋다.

int max_i = 0;
for (int i = 0; i < 26; i++) {
    if (cnt[max_i] < cnt[i]) {
        max_i = i;
    }
}

그 다음은 가장 많은 알파벳의 인덱스를 가져오는 부분이다. 인덱스를 가져오게 되면 해당 알파벳이 뭔지도 'A'를 더하면 알 수 있고 cnt의 인덱스로 넣어 카운팅 결과도 알 수 있게 된다. 

int check = 0;
for (int i = 0; i < 26; i++) {
    if (cnt[max_i] == cnt[i]) check++;
}

if (check == 1) printf("%c\n", max_i + 'A');
else printf("?\n");

그 다음에는 카운팅 결과 중 가장 큰 것의 개수를 세는 데 만약 check가 1이면 중복이 없는 것이므로 해당 카운팅 값에 'A'를 더해 알파벳을 출력하지만 1이 아니라면(1 이상이라면) ?를 출력한다.

반응형

댓글