백준 PlayStation이 아니에요

KIMYEONGJUN·2025년 12월 3일
post-thumbnail

문제

내가 생각했을때 문제에서 원하는부분

첫째 줄에 문자열의 길이를 나타내는 정수 N이 주어진다. (1 ≤ N ≤ 50)
둘째 줄에 문자열이 주어진다.
문자열은 영문 대문자와 숫자로만 이루어져 있다.

첫째 줄에 피돌이가 문자열을 고치고 난 뒤의 문자열을 출력한다.
만약 만족하는 문자열이 여러 개라면, 그중 가장 긴 문자열을 출력한다.
가능한 모든 입력에 대해 가장 긴 문자열이 존재하며 유일함을 증명할 수 있다.

내가 이 문제를 보고 생각해본 부분

초기 설정(입출력 및 StringBuilder)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
이 부분은 키보드 입력(표준 입력)을 효율적으로 읽어들이기 위해 BufferedReader를 준비하는 코드이다. 
System.in은 바이트 단위 입력인데, InputStreamReader를 통해 문자 단위로 읽을 수 있게 변환해 준다.
StringBuilder sb = new StringBuilder();
StringBuilder는 변경될 문자열을 효율적으로 만들 때 사용된다.
String 객체는 한번 만들어지면 내용을 바꿀 수 없어서, 문자열을 계속 수정하면 성능 저하가 발생할 수 있다.
int N = Integer.parseInt(br.readLine());
문제에서 주어지는 첫 줄의 '문자열 길이'를 읽어서 N이라는 정수 변수에 저장한다. 
이 N은 아래 for 반복문이 몇 번 실행되어야 할지를 결정하는 데 사용된다.
String str = br.readLine();
두 번째 줄에 입력되는 실제 문자열을 str 변수에 저장한다.
패턴 추적 상태 변수(time)
int time = 0;
time 변수는 현재 우리가 "PS" 패턴을 얼마나 찾아냈는지 상태를 나타내는 중요한 변수이다.
time = 0 : 아직 'P'를 찾지 못했거나, 이전에 찾던 패턴이 깨진 초기 상태를 의미합니다. 'P'를 기다리는 중이다.
time = 1 : 'P'를 하나 찾아낸 상태를 의미한다. 
이제 그 다음에 'S'가 오는지 지켜본다.
time = 2 : 'P' 다음에 'S'가 와서 "PS" 패턴이 완성된 상태를 의미한다. 
이제 그 다음에 '4' 또는 '5'가 오는지 지켜본다.
문자열 순회 및 패턴 처리(for 반복문)
for(int i = 0; i < N; i++) { ... }
이 반복문은 str 문자열의 첫 글자부터 마지막 글자(N-1번째 글자)까지 차례대로 하나씩 확인한다.
char cur = str.charAt(i);
반복문이 실행될 때마다 현재 보고 있는 글자를 cur 변수에 저장한다.
조건별 로직
if(cur == 'P') { ... }
만약 현재 글자(cur)가 'P'라면, 우리는 'P'를 찾았으므로 time을 1로 변경한다. 
그리고 'P'는 제거 대상이 아니기 때문에 sb.append(cur);를 통해 결과 문자열에 추가한다.
else if(cur == 'S' && time == 1) { ... }
현재 글자가 'S'이고, 바로 직전까지 'P'를 찾은 상태(즉, time이 1)였다면, "PS" 패턴이 완성된 것이다. 
그래서 time을 2로 변경하고, 'S'도 제거 대상이 아니므로 sb.append(cur);를 통해 결과 문자열에 추가한다.
else if((cur == '4' || cur == '5') && time == 2) { ... }
현재 글자가 '4' 또는 '5'이고, 바로 직전까지 "PS" 패턴을 찾은 상태(즉, time이 2)였다면, "PS4" 또는 "PS5" 패턴이 완성된 것이다.
이때 문제 조건에 따라 이 숫자('4' 또는 '5')는 제거해야 한다.
그래서 sb.append(cur);를 하지 않고, continue;를 사용하여 현재 반복문의 나머지 부분을 건너뛰고 바로 다음 글자를 확인하러 간다.
또한, time을 다시 0으로 초기화하여, 이 "PS4/5" 패턴 이후부터는 다시 새로운 'P'를 찾도록 준비한다.
else { ... }
위의 어떤 if나 else if 조건에도 해당하지 않는 경우이다. 
이는 'P'나 'S'를 찾았는데 다음에 기대하던 문자가 오지 않았거나, 아예 'P', 'S', '4', '5'와 무관한 글자가 나온 경우이다.
이런 상황은 "PS4"나 "PS5" 패턴을 만들지 않으므로, time을 다시 0으로 초기화하여 새로운 패턴을 찾도록 한다. 
그리고 현재 글자(cur)는 제거 대상이 아니기 때문에 sb.append(cur);를 통해 결과 문자열에 추가한다.
결과 출력 및 자원 해제
System.out.println(sb);
반복문이 모두 끝나면 sb에는 "PS4"나 "PS5"에서 '4'나 '5'만 제거된 최종 문자열이 만들어져 있다. 
이 문자열을 콘솔에 출력한다.
br.close();
BufferedReader는 시스템 자원을 사용하므로, 사용 후에는 반드시 닫아주어 자원 누수를 방지한다.

코드로 구현

package baekjoon.baekjoon_31;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

// 백준 32132번 문제
public class Main1225 {
    public static void main(String[] args) throws IOException {
        // BufferedReader를 사용하여 표준 입력(System.in)에서 데이터를 효율적으로 읽어옵니다.
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // StringBuilder를 사용하여 변경된 문자열을 효율적으로 구성합니다.
        // String은 불변(immutable)이므로 문자열 조작이 많을 때 StringBuilder가 성능상 유리합니다.
        StringBuilder sb = new StringBuilder();

        // 첫 번째 줄에서 문자열의 길이 N을 읽어 정수로 변환합니다.
        // 이 문제에서는 N이 for 루프의 반복 횟수를 결정하는 데 사용됩니다.
        int N = Integer.parseInt(br.readLine());
        // 두 번째 줄에서 처리할 실제 문자열을 읽어옵니다.
        String str = br.readLine();

        // 'PS' 패턴의 상태를 추적하기 위한 변수입니다.
        // time = 0: 'P'를 아직 찾지 못했거나 패턴이 깨진 상태
        // time = 1: 'P'를 찾은 상태
        // time = 2: 'PS'를 찾은 상태 (이제 '4' 또는 '5'가 올 차례)
        int time = 0;

        // 입력 문자열을 처음부터 끝까지 순회합니다. (인덱스 0부터 N-1까지)
        for(int i = 0; i < N; i++) {
            // 현재 문자를 가져옵니다.
            char cur = str.charAt(i);

            // 현재 문자와 'time' 변수의 상태에 따라 로직을 처리합니다.
            if(cur == 'P') {
                // 현재 문자가 'P'인 경우, 'P'를 찾은 상태로 'time'을 업데이트합니다.
                time = 1;
                // 'P'는 항상 결과 문자열에 포함되므로 StringBuilder에 추가합니다.
                sb.append(cur);
            } else if(cur == 'S' && time == 1) {
                // 현재 문자가 'S'이고, 바로 직전에 'P'를 찾았던 상태(time == 1)인 경우,
                // 'PS' 패턴이 완성되었으므로 'time'을 업데이트합니다.
                time = 2;
                // 'S'도 항상 결과 문자열에 포함되므로 StringBuilder에 추가합니다.
                sb.append(cur);
            } else if((cur == '4' || cur == '5') && time == 2) {
                // 현재 문자가 '4' 또는 '5'이고, 바로 직전에 'PS' 패턴을 찾았던 상태(time == 2)인 경우,
                // "PS4" 또는 "PS5" 패턴이 완성됩니다.
                // 문제 조건에 따라 이 숫자('4' 또는 '5')는 제거해야 하므로,
                // sb.append(cur)를 실행하지 않고 다음 반복으로 건너뜁니다 (continue).
                // 이 숫자를 건너뛴 후에는 'time' 상태를 초기화하여 새로운 패턴을 찾을 준비를 합니다.
                time = 0;
                continue; // 현재 문자를 sb에 추가하지 않고 다음 루프를 시작합니다.
            } else {
                // 위의 어떤 조건에도 해당하지 않는 경우 (예: 'PS' 다음 '3'이 오거나, 'P' 다음 'A'가 오는 경우 등),
                // 'PS' 패턴 추적이 깨졌다고 판단하고 'time' 상태를 초기화합니다.
                time = 0;
                // 현재 문자는 제거 대상이 아니므로 StringBuilder에 추가합니다.
                sb.append(cur);
            }
        }

        // 최종적으로 완성된 문자열을 시스템 표준 출력(콘솔)에 출력합니다.
        System.out.println(sb);

        // 사용했던 BufferedReader 자원을 닫아줍니다.
        br.close();
    }
}

마무리

코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.

profile
Junior backend developer

0개의 댓글