백준 새로운 문자열 만들기

KIMYEONGJUN·2025년 12월 27일
post-thumbnail

문제

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

첫 번째 줄에 주어지는 문자열의 개수 T가 주어진다. (1 ≤ T ≤ 100)
두 번째 줄부터 T개의 줄에 걸쳐 문자열 S가 주어진다.
각 줄마다 주어지는 문자열 S의 길이는 1이상 20이하이다.

T개의 줄에 걸쳐 주어진 문자열 S마다 조건을 모두 만족하는 문자열 X를 출력한다.

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

입력 처리 및 초기 설정:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); : 표준 입력으로부터 데이터를 효율적으로 읽어오기 위한 BufferedReader를 생성한다.
StringBuilder sb = new StringBuilder(); : 여러 테스트 케이스의 결과를 문자열로 합쳐서 한 번에 출력하기 위해 StringBuilder를 사용한다.
int T = Integer.parseInt(br.readLine()); : 첫 줄에 주어지는 테스트 케이스의 개수 T를 읽어 정수형으로 변환한다.
테스트 케이스 반복:
for(int i = 0; i < T; i++) { ... } : T개의 테스트 케이스 각각에 대해 반복하여 문제를 해결한다.
문자열 처리:
String S = br.readLine(); : 각 테스트 케이스마다 한 줄씩 문자열 S를 읽어온다.
String reversedS = new StringBuilder(S).reverse().toString(); : S의 역순 문자열을 만든다. 
예를 들어 S = KITPA라면 reversedS는 APTIK가 된다. 
이 reversedS를 사용하여 X가 S로 시작하면서 reverse(X)도 S로 시작하는 (즉 X가 reversedS로 끝나는) 조건을 만족시킬 것이다.
int sLength = S.length(); : S의 길이를 변수에 저장하여 여러 번 사용해야 할 때 편리하게 접근하도록 한다.
최대 겹치는 부분 찾기 (bestMatchLength):
int bestMatchLength = 0; : S와 reversedS 사이에 겹치는 가장 긴 부분의 길이를 저장할 변수이다. 
초기값은 0이다.
for(int j = 0; j < sLength; j++) { ... } : S의 끝 부분과 reversedS의 시작 부분이 얼마나 겹칠 수 있는지 확인하는 과정이다.
예를 들어, S = BANANA이고 reversedS = ANANAB일 때:
j = 0: suffixOfS = "BANANA" (S의 전체), prefixOfReversedS = "ANANAB" (reversedS의 전체).
같지 않다.
j = 1: suffixOfS = "ANANA" (S의 두 번째부터), prefixOfReversedS = "ANANA" (reversedS의 첫 번째부터 5개).
이 부분이 일치한다.
이때 bestMatchLength는 5가 된다.
S.substring(j)는 S의 j번째 인덱스부터 끝까지의 부분 문자열, 즉 S의 접미사를 의미한다.
reversedS.substring(0, sLength - j)는 reversedS의 0번째 인덱스부터 sLength - j 길이만큼의 부분 문자열, 즉 reversedS의 접두사를 의미한다.
sLength - j는 suffixOfS의 길이와 같다.
if(suffixOfS.equals(prefixOfReversedS)) : S의 접미사와 reversedS의 접두사가 같은지 비교한다.
bestMatchLength = suffixOfS.length(); : 만약 일치한다면, 이 길이가 현재까지 찾은 가장 긴 겹치는 부분이다.
break; : 가장 긴 겹치는 부분을 찾았으므로, 더 짧은 일치 여부를 탐색할 필요 없이 반복문을 종료한다.
결과 문자열 생성:
String result = S + reversedS.substring(bestMatchLength); : 최종 문자열 X를 만든다.
S는 X의 시작 부분이 된다.
reversedS.substring(bestMatchLength)는 reversedS에서 bestMatchLength만큼의 겹치는 부분을 제외한 나머지 뒷부분을 의미한다. 
이 부분이 S 뒤에 붙여져서 reverse(X)가 S로 시작하게 만드는 역할을 한다.
예를 들어, S = BANANA일 때 bestMatchLength = 5이고 reversedS = ANANAB이다.
reversedS.substring(5)는 B가 된다.
result = "BANANA" + "B" = "BANANAB"가 된다.
S = KITPA일 때 bestMatchLength = 0 (겹치는 부분이 없음) 이고 reversedS = APTIK이다.
reversedS.substring(0)은 APTIK가 된다.
result = "KITPA" + "APTIK" = "KITPAPTIK"가 된다.
결과 출력:
sb.append(result).append("\n"); : 생성된 result 문자열을 StringBuilder에 추가하고 줄 바꿈 문자를 넣어준다.
System.out.print(sb.toString()); : 모든 테스트 케이스의 처리가 끝나면, StringBuilder에 저장된 전체 결과를 한 번에 출력한다.
br.close(); : 사용했던 BufferedReader를 닫아 자원을 해제한다.

코드로 구현

package baekjoon.baekjoon_31;

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

// 백준 30089번 문제
public class Main1249 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder(); // 결과를 한 번에 출력하기 위해 StringBuilder 사용

        int T = Integer.parseInt(br.readLine()); // 테스트 케이스의 개수 T 입력

        for (int i = 0; i < T; i++) {
            String S = br.readLine(); // 문자열 S 입력
            String reversedS = new StringBuilder(S).reverse().toString(); // S를 뒤집은 문자열 생성
            int sLength = S.length(); // S의 길이

            int bestMatchLength = 0; // S와 reversedS 간의 가장 긴 겹치는 부분 길이

            // S의 접두사가 reversedS의 접미사와 일치하는 가장 긴 부분을 찾습니다.
            // i는 S의 길이, 즉 S의 i번째까지의 접두사와 reversedS의 뒤에서 i번째까지의 접미사가 겹치는지 확인
            for (int j = 0; j < sLength; j++) {
                // S의 j부터 끝까지의 부분 문자열 (S의 접미사)
                String suffixOfS = S.substring(j);
                // reversedS의 0부터 S.length()-j까지의 부분 문자열 (reversedS의 접두사)
                // 이 두 문자열의 길이가 같아야 비교 가능
                String prefixOfReversedS = reversedS.substring(0, sLength - j);

                if (suffixOfS.equals(prefixOfReversedS)) {
                    // S의 접미사와 reversedS의 접두사가 일치하면, 이 길이가 가장 긴 일치 길이
                    bestMatchLength = suffixOfS.length();
                    break; // 가장 긴 길이를 찾았으므로 더 이상 찾을 필요 없음
                }
            }

            // S + reversedS의 매칭되지 않은 부분 (bestMatchLength 이전 부분)
            String result = S + reversedS.substring(bestMatchLength);
            sb.append(result).append("\n"); // 결과 저장
        }

        System.out.print(sb.toString()); // 모든 결과 한 번에 출력
        br.close();
    }
}

마무리

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

profile
Junior backend developer

0개의 댓글