와드의 블로그

14405번: 피카츄 본문

PS/B.O.J

14405번: 피카츄

Ward 2026. 3. 29. 18:25

문제

피카츄는 "pi", "ka", "chu" 세 가지 음절을 발음할 수 있으며, 이 세 음절을 합친 단어만 발음할 수 있습니다. 어떤 문자열이 주어졌을 때, 피카츄가 발음할 수 있는 문자열인지 아닌지 판별하는 문제입니다.

  • 입력: 첫째 줄에 알파벳 소문자로만 이루어진 문자열 S가 주어집니다. (문자열의 길이는 최대 5000)
  • 출력: 문자열 S가 "pi", "ka", "chu" 로만 이루어져 있으면 "YES"를, 아니면 "NO"를 출력합니다.

링크: https://www.acmicpc.net/problem/14405

풀이: 인덱스 기반의 패턴 매칭

정규표현식이나 replaceAll 메서드를 사용할 수도 있지만, 주어진 코드는 문자열의 첫 글자부터 끝까지 직접 인덱스(idx)를 이동시키며 해당 위치의 부분 문자열을 검증하는 정석적인 파싱 방식을 사용했습니다.

  1. 문자열 순회 및 첫 글자 판별: 문자열의 끝에 도달할 때까지 while 문을 통해 idx를 증가시킵니다. 현재 인덱스의 문자(c)가 'p', 'k', 'c' 중 하나인지 확인합니다.
  2. 부분 문자열 검사 (substring):
    • 문자가 'p'인 경우, 2글자("pi")가 이어지는지 확인합니다.
    • 문자가 'k'인 경우, 2글자("ka")가 이어지는지 확인합니다.
    • 문자가 'c'인 경우, 3글자("chu")가 이어지는지 확인합니다.
  3. 인덱스 초과 예외 처리 (안전성 확보): 검사하려는 패턴의 길이만큼 남은 문자열이 충분한지 먼저 확인합니다. (idx + 2 > s.length() 등) 이를 통해 substring 호출 시 발생할 수 있는 StringIndexOutOfBoundsException을 미연에 방지합니다.
  4. 불일치 판별 및 종료: 만약 위 패턴과 일치하지 않거나 완전히 다른 문자가 등장했다면 플래그(flag)를 false로 변경합니다. 유효하지 않은 문자열임이 확인되는 즉시 "NO"를 출력하고 프로그램을 종료(return)하여 불필요한 연산을 막습니다. 끝까지 무사히 순회했다면 "YES"를 출력합니다.

코드

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
       BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
       BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

       String s = br.readLine();
       int idx = 0;
       
       while (idx < s.length()) {
          char c = s.charAt(idx);
          boolean flag = true;
          
          if (c == 'p') {
             // 남은 길이가 부족하거나 "pi"가 아니면 실패
             if (idx + 2 > s.length() || !s.substring(idx, idx + 2).equals("pi")) {
                flag = false;
             }
             idx += 2;
          } else if (c == 'k') {
             // 남은 길이가 부족하거나 "ka"가 아니면 실패
             if (idx + 2 > s.length() || !s.substring(idx, idx + 2).equals("ka")) {
                flag = false;
             }
             idx += 2;
          } else if (c == 'c') {
             // 남은 길이가 부족하거나 "chu"가 아니면 실패
             if (idx + 3 > s.length() || !s.substring(idx, idx + 3).equals("chu")) {
                flag = false;
             }
             idx += 3;
          } else {
             // 'p', 'k', 'c'로 시작하지 않으면 무조건 실패
             flag = false;
          }

          // 패턴이 일치하지 않는 경우 즉시 NO 출력 후 종료
          if (!flag) {
             bw.write("NO");
             bw.flush();
             return;
          }
       }

       // 모든 문자열을 성공적으로 확인한 경우
       bw.write("YES");

       bw.flush();
       bw.close();
       br.close();
    }
}

알고리즘 분류

문자열 처리 (String), 파싱 (Parsing)

'PS > B.O.J' 카테고리의 다른 글

1094번: 막대기  (0) 2026.03.30
5430번: AC  (0) 2026.03.29
큰 수 A+B (2)  (0) 2026.03.29
12869번: 뮤탈리스크  (0) 2026.03.28
4179번: 불!  (0) 2026.03.28