BOJ 10942 팰린드롬? (Java)

사람·2025년 1월 26일
0

BOJ

목록 보기
19/76

문제

명우는 홍준이와 함께 팰린드롬 놀이를 해보려고 한다.

먼저, 홍준이는 자연수 N개를 칠판에 적는다. 그 다음, 명우에게 질문을 총 M번 한다.

각 질문은 두 정수 S와 E(1 ≤ S ≤ E ≤ N)로 나타낼 수 있으며, S번째 수부터 E번째 까지 수가 팰린드롬을 이루는지를 물어보며, 명우는 각 질문에 대해 팰린드롬이다 또는 아니다를 말해야 한다.

예를 들어, 홍준이가 칠판에 적은 수가 1, 2, 1, 3, 1, 2, 1라고 하자.

S = 1, E = 3인 경우 1, 2, 1은 팰린드롬이다.
S = 2, E = 5인 경우 2, 1, 3, 1은 팰린드롬이 아니다.
S = 3, E = 3인 경우 1은 팰린드롬이다.
S = 5, E = 7인 경우 1, 2, 1은 팰린드롬이다.
자연수 N개와 질문 M개가 모두 주어졌을 때, 명우의 대답을 구하는 프로그램을 작성하시오.

입력
첫째 줄에 수열의 크기 N (1 ≤ N ≤ 2,000)이 주어진다.

둘째 줄에는 홍준이가 칠판에 적은 수 N개가 순서대로 주어진다. 칠판에 적은 수는 100,000보다 작거나 같은 자연수이다.

셋째 줄에는 홍준이가 한 질문의 개수 M (1 ≤ M ≤ 1,000,000)이 주어진다.

넷째 줄부터 M개의 줄에는 홍준이가 명우에게 한 질문 S와 E가 한 줄에 하나씩 주어진다.

출력
총 M개의 줄에 걸쳐 홍준이의 질문에 대한 명우의 답을 입력으로 주어진 순서에 따라서 출력한다. 팰린드롬인 경우에는 1, 아닌 경우에는 0을 출력한다.

예제 입력 1
7
1 2 1 3 1 2 1
4
1 3
2 5
3 3
5 7
예제 출력 1
1
0
1
1

접근

앞에서부터 읽으나 뒤에서부터 읽으나 똑같은 문자열을 팰린드롬(palindrome)이라고 한다.**

8글자로 이루어진 문자열이 팰린드롬이려면, 2번째~7번째 글자로 이루어진 문자열이 팰린드롬임과 동시에 첫번째 글자와 8번째 글자가 같아야 한다.
2번째~7번째 글자가 팰린드롬이려면 3번째~6번째 글자가 팰린드롬임과 동시에 2번째 글자와 7번째 글자가 같아야 하고.
이런 식으로 전체 문자열의 팰린드롬 여부가 하위 부분 문제로 결정되기 때문에 다이나믹 프로그래밍으로 접근할 수 있다.

구현

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

class Main {
    static int[] nums;
    static int[][] dp;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        nums = new int[N + 1];
        dp = new int[N + 1][N + 1];

        StringTokenizer st = new StringTokenizer(br.readLine());
        for (int i = 1; i <= N; i++) {
            nums[i] = Integer.parseInt(st.nextToken());
        }

        int M = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < M; i++) {
            st = new StringTokenizer(br.readLine());
            int S = Integer.parseInt(st.nextToken());
            int E = Integer.parseInt(st.nextToken());
            if (isPalindrome(S, E)) {
                sb.append(1).append("\n");
            } else {
                sb.append(0).append("\n");
            }
        }
        System.out.print(sb.toString());
    }

    private static boolean isPalindrome(int left, int right) {
        if (left >= right) {
            return true;
        }

        if (dp[left][right] == 1) {
            return true;
        } else if (dp[left][right] == -1){
            return false;
        }

        if (nums[left] == nums[right] && isPalindrome(left + 1, right - 1)) {
            dp[left][right] = 1;
            return true;
        }

        dp[left][right] = -1;
        return false;
    }
}

dp[i][j] 배열에 i번째 수부터 j번째 수까지가 팰린드롬인지 여부를 메모이제이션했다. 값이 1이면 팰린드롬이 맞다는 뜻, -1이면 팰린드롬이 아니라는 뜻.

  • left >= right이면 확인해야 할 문자가 더 이상 남아 있지 않으므로 true를 리턴해주었다.

  • dp[i][j] 배열의 값이 0이 아니면 이미 팰린드롬 여부가 메모이제이션이 되어 있다는 뜻이니 바로 그 값에 따라 true/false를 리턴해주었다.

  • dp[i][j] 배열의 값이 0이면

  1. left번째 수와 right번째 수가 같은지 확인한 후,
  2. left+1번째 수부터 right-1번째 수까지가 팰린드롬인지 확인하기 위해 재귀 호출을 해주었다.

위 1번과 2번을 모두 만족시키는 경우에만 팰린드롬으로 판정했다.

profile
알고리즘 블로그 아닙니다.

0개의 댓글