본문 바로가기

DEVELOP/Algorithm

[C] SW Expert Academy 문제풀이 :: 2007번

반응형


30개의 문자열 내부에서 반복되는 마디의 개수를 출력하는 프로그램. 알고리즘 구현은 쉬운데 C의 문자열 처리가 익숙치 않아서 시간이 오래 걸렸다. 파이썬이었다면 그냥 한 번에 되는 것들을 C로 문자열(배열) 안의 요소들을 하나하나 처리해주느라 번거로웠다. 오래 전에 파이썬을 처음 배울 때, 파이썬의 장점이라고 들었던, 그 때는 느끼지 못했던 간편함들이 크게 느껴졌다.



문제


https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5P1kNKAl8DFAUq&categoryId=AV5P1kNKAl8DFAUq&categoryType=CODE


패턴에서 반복되는 부분을 마디라고 부른다. 문자열을 입력 받아 마디의 길이를 출력하는 프로그램을 작성하라. 



풀이


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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <string.h>
#include <malloc.h>
 
int groupChecker(char str[], int n) {
    char *strCut1, *strCut2;
    char flag = 0;
    strCut1 = (char*)malloc(sizeof(char)*(n+1));
    strCut2 = (char*)malloc(sizeof(char)*(n+1));
 
    for (int i = 0; i < n; i++) {
        strCut1[i] = str[i];
    }
    strCut1[n] = '\0';
 
    for (int i = 0; i < 30 / n; i++) {
        for (int j = 0; j < n; j++) {
            strCut2[j] = str[n * i + j];
        }
        strCut2[n] = '\0';
 
        if (strcmp(strCut1, strCut2) == 0) {
            flag = 1;
        }
        else {
            flag = 0;
            break;
        }
    }
    
    if (flag == 1) {
        return n;
    }
    else {
        return 0;
    }
}
 
int main() {
    int tc;
    char inStr[30 + 1];
    scanf("%d"&tc);
    
    for (int t = 0; t < tc; t++) {
        scanf("%s", inStr);
        int flag;
        for (int i = 0; i < 10; i++) {
            flag = groupChecker(inStr, i + 1);
            if (flag != 0) {
                printf("#%d %d\n", t+1, flag);
                break;
            }
        }
    }
 
    return 0;
}
cs


우선 헤더 3개를 불러온다. 기본적인 표준입출력 <stdio.h>, 문자열 처리를 도와주는 <string.h>, 그리고 동적할당을 해주는 <malloc.h>.


메인 함수 이전에 문자열과 정수 n을 받고, n개 글자수의 마디가 반복되는지 확인해주는 함수를 만들었다. 마디가 반복된다면 n을, 아니면 0을 리턴한다.


우선 30개의 문자열 중 맨 처음 n개를 담을 strCut1 변수와, 이후 n개 단위로 잘라서 문자열을 넣을 strCut2를 만들었다. 예를 들어 n이 3이라면 strCut1에는 0,1,2번째 문자를 담는다. 그리고 (3,4,5), (6,7,8) ... (27,28,29)번째 문자를 strCut2에 담아 원본인 strCut1과 계속 반복한다.


만약 strCut1과 strCut2과 같다면, flag 변수를 1로 바꿔주고 비교를 계속 한다. 하지만 다르다면, 마디수는 n개가 아니라고 할 수 있으므로 flag를 0으로 하고 비교를 그만둔다.


for문이 다 돌아간 후에 flag가 1이라면 n개 글자 수의 마디가 반복되는 것이므로 n을 리턴, 0이라면 중간에 다른 부분이 있어 break한 것이므로 0을 리턴한다.


동적할당을 쓴 이유는 비교할 문자열의 크기가 n에 따라 달라지기 때문. n+1개의 크기를 할당한 이유는 n개의 문자와 null을 집어넣기 위해서이다.


문자열 비교는 strcmp()함수를 썼다. 실제 함수의 의미는 좀 다르지만, 문자열의 일치 여부를 확인하는데 사용하기에 간편하다. 두 개의 문자열이 같다면 0을 리턴한다. 


메인 함수에는 테스트 케이스를 받고, 그만큼 30 길이의 문자열 inStr을 받아 n의 범위인 1부터 10까지 groupChecker(inStr, n)을 확인해주는 방법을 썼다. 작은 수부터 해야 ABCABCABCABC를 3 길이 마디의 10개 반복으로 인식하고 리턴한다. 만약 뒤에서부터 한다면 9 길이 마디의 3개 반복과 3개 문자의 나머지로 인식할 것.

반응형