복기

 

먼저 이 문제는 제가 풀지못한 문제입니다. 결국 다른 사람의 풀이를 보고 풀었죠...ㅜㅜ

 

구슬이 중간에서 터지면 위의 구슬이 떨어져서 밑이랑 색이 같으면 또 터지는 뿌요뿌요 게임처럼 삭제된 문자열 좌우 문자를 붙혀서 A 문자열이 나오면 또 삭제를 해줘야하는 점이 아마 이 문제를 까다롭게 만드는 점인 것 같은데요.

 

먼저, 아래는 다른 사람 풀이를 보고 작성한 코드입니다.

 

더보기

 

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
58
59
60
61
// 검열
#include <stdio.h>
#pragma warning(disable : 4996)
char A[35], T[300015], s1[300015], s2[300015], b;
int len, l, r, t1, t2;
 
char check(void) {
    if (0 == b) {
        if (t1 < len) return 0;
        for (int i = 1; i <= len; i++) {
            if (s1[t1 - i] != A[len - i]) {
                return 0;
            }
        }
    }
    else {
        if (t2 < len) return 0;
        for (int i = 1; i <= len; i++) {
            if (s2[t2 - i] != A[i - 1]) {
                return 0;
            }
        }
    }
    return 1;
}
int main(void) {
    scanf("%s %s", A, T);
    for (len = 0; A[len]; len++);
    for (r = 0; T[r + 1]; r++);
 
    while (l <= r) {
        if (0 == b) {
            s1[t1++= T[l++];
            if (s1[t1 - 1== A[len - 1]) {
                if (check()) {
                    t1 -= len;
                    b ^= 1;
                }
            }
        }
        else {
            s2[t2++= T[r--];
            if (s2[t2 - 1== A[0]) {
                if (check()) {
                    t2 -= len;
                    b ^= 1;
                }
            }
        }
    }
    b = 0;
    while (t2) {
        s1[t1++= s2[--t2];
        if (s1[t1 - 1== A[len - 1]) {
            if (check())
                t1 -= len;
        }
    }
    s1[t1] = 0;
    return !printf("%s\n", s1);
}// 1
cs

 

위 코드가 제가 맨처음 작성했던 코드와 다른 점은 비교를 앞에서부터 하는가 뒤에서부터 하는가 입니다.

 

글이 좀 애매한데 어떤 의미인가 하면

 

 
 A: aac


 T: aaaaaaccc

 

위의 입력이 주어졌을 때, T의 왼쪽에서부터 A 문자열과 일치하는 문자열을 찾는 상황에서

 

앞에서부터 비교한다는건 (a a c 순으로 비교) 아래와 같이 일치하는 문자열을 찾았을 때 인덱스가 4 가 되는 것이고

 

뒤에서부터 비교한다는건 (c a a 순으로 비교) 인덱스가 6 일 때 아래 상황이 되는 겁니다. 

 

 
 aaaa (aac) cc



별 것 아닌 차이 같지만 앞문자부터 비교하면 삭제후 다음 인덱스부터 앞방향 탐색 범위에 삭제 때문에 끊기고 뒤에 남은 문자들이 포함되지 못합니다. 추가로 뭔 짓거리를 더 해줘야 하는 셈이죠. : aaaa (c->) c

 

반면에 뒷문자부터 비교하면 삭제후 다음 인덱스로 옮겨도 버퍼 안의 내용과 비교하면 탐색하던 방향 그대로 뒤에 남은 문자들을 포함해서 비교할 수 있죠 : aaaa (<-c) c

 

물론 전자처럼 구현해도 관계는 없을 겁니다. 하지만, 확실히 후자가 쉬운 길인 것 같네요.

 

더보기
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 검열
#include <stdio.h>
#include <string.h>
#pragma warning(disable : 4996)
volatile char A[33], T[300015];
volatile int len, f, r;
 
struct Stack {
    char data[300015];
    int top;
} s1, s2;
void Push(Stack *ps, char in)    { ps->data[ps->top++= in;    }
char Pop(Stack *ps)                { return ps->data[--(ps->top)];    }
int GetCount(Stack *ps)            { return ps->top; }
 
int main(void) {
    scanf("%s %s", A, T);
    for (len = 0; A[len]; len++);
    for (r = 0; T[r]; r++);
    
    char bSame;
    int n;
    while (r - f >= len) {
        while (r - f >= len) {
            bSame = 1;
            for (int i = 0; i < len; i++) {
                if (T[f + i] != A[i]) {
                    bSame = 0;
                    break;
                }
            }
            if (bSame == 0
                Push(&s1, T[f++]);
            else {
                n = GetCount(&s1);
                n = n < len - 1 ? n : len - 1;
                f += len - n;
                for (int i = n - 1; i >= 0; i--)
                    T[f + i] = Pop(&s1);
            }
            while (GetCount(&s2) > 0 && r - f < len) {
                T[r++= Pop(&s2);
                T[r] = 0;
            }
            if (bSame == 1break;
        }
        while (r - f >= len) {
            bSame = 1;
            n = r - len;
            for (int i = 0; i < len; i++) {
                if (T[n + i] != A[i]) {
                    bSame = 0;
                    break;
                }
            }
            if (bSame == 0
                Push(&s2, T[--r]);
            else {
                n = GetCount(&s2);
                n = n < len - 1 ? n : len - 1;
                r -= len - n;
                T[r] = 0;
                for (int i = n; i > 0; i--)
                    T[r - i] = Pop(&s2);
            }
            while (GetCount(&s1) > 0 && r - f < len) 
                T[--f] = Pop(&s1);
            if (bSame == 1break;
        }
    }
    while (GetCount(&s1) > 0)
        T[--f] = Pop(&s1);
    while (GetCount(&s2) > 0)
        T[r++= Pop(&s2);
    T[r] = 0;
    return !printf("%s\n", T + f);
} // 2
cs

 

 

위 코드는 전자 방법으로 푼 코드이고 문자열 삭제후 뒤에 남은 문자랑 비교하려고 (A 문자열 길이 -1) 개 문자를 저장 버퍼에서 빼는... 쓰잘데기 없이 일을 만들어서 하는 방법입니다. 

 

그리고, 사실 이 코드는 틀린 코드입니다. 이유는 잘 모르겠지만 "출력 초과"로 나오네요.. ㅠ_ㅠ

 

'일단 머리좀 식히고 답을 잊을 때쯤 다시와서 틀린 이유를 찾아보자' 는 의미에서 이 코드도 남깁니다.

 

혹여 지나가던 고수님께서 이유를 집어 주신다면 감사할 따름이고요 ㅎㅎ.

 

복기끝

 

 

사실 지금 든 생각이지만 이 것도 시작 문자 한 개만 버퍼랑 비교하고 나머지는 T랑 비교하면 전자나 후자나 다를게 없겠다는 생각이 드네요............. 

지금까지 쓴 글이... ++'

'개발 > c' 카테고리의 다른 글

[백준] 17825 주사위 윷놀이  (0) 2020.04.24
[백준] 17822 원판 돌리기  (0) 2020.04.22
[백준] 4179 불!  (0) 2018.12.13
winpcap pcap_pkthdr 구조체에서 caplen과 len의 차이  (0) 2018.12.01
ffmpeg 라이브러리 사용법  (2) 2018.11.16

+ Recent posts