백준 1522번: 문자열 교환

알고리즘Java코딩 테스트백준
avatar
2025.05.25
·
3 min read

문제

a와 b로만 이루어진 문자열이 주어질 때,  a를 모두 연속으로 만들기 위해서 필요한 교환의 회수를 최소로 하는 프로그램을 작성하시오.

이 문자열은 원형이기 때문에, 처음과 끝은 서로 인접해 있는 것이다.

예를 들어,  aabbaaabaaba이 주어졌을 때, 2번의 교환이면 a를 모두 연속으로 만들 수 있다.

입력

첫째 줄에 문자열이 주어진다. 문자열의 길이는 최대 1,000이다.

출력

첫째 줄에 필요한 교환의 회수의 최솟값을 출력한다.


나의 풀이

  • 문자열 s에서 'a'의 개수 aCnt를 센다.

  • 원형 구조를 고려해 문자열을 s + s로 연결하여 circularString 생성

  • circularString에서 누적합 배열 prefixSum을 만들어서
    prefixSum[i]는 인덱스 0부터 i-1까지의 'b' 개수 합을 저장

  • 길이 aCnt인 윈도우(슬라이딩 윈도우)를 circularString 전체에 걸쳐 이동하면서
    해당 구간 내 'b' 개수를 빠르게 계산 (prefixSum[end] - prefixSum[start])

  • 모든 윈도우에 대해 최소 'b' 개수를 찾아 출력

나의 코드

import java.io.*;

/**
 * 백준 1522 문자열 교환 (실버 1) - 슬라이딩 윈도우
 * <a href="https://www.acmicpc.net/problem/1522">...</a>
 */
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        int aCnt = 0;

        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == 'a') aCnt++;
        }

        String circularString = s + s;
        int[] prefixSum = new int[circularString.length() + 1];
        for (int i = 1; i <= circularString.length(); i++) {
            prefixSum[i] = prefixSum[i - 1] + (circularString.charAt(i - 1) == 'b' ? 1 : 0);
        }

        int answer = s.length();
        for (int start = 0; start <= circularString.length() - aCnt; start++) {
            int end = start + aCnt;
            int bCnt = prefixSum[end] - prefixSum[start];

            answer = Math.min(answer, bCnt);
        }

        System.out.println(answer);
    }
}






- 컬렉션 아티클