Problem Solving/Else

BOJ 1509 : 팰린드롬 분할

PS리버싱마크해커박종휘TV 2022. 4. 5. 15:30

3줄 요약:

  • DP

 

난 도대체 왜 팰린드롬을 분할하는 것인지 모르겠다. 어느 문제에서는 유사회문인지를 출력하라 하지 않나, 어느 문제에서는 공장을 개설하지 않나... 팰린드롬은 내가 제일 싫어하는 문제 중 하나이다.

 

 

이 문제를 풀 때는 DP를 두 번 사용하여 풀 수 있다.

  • dp[i][j] = i번째 문자부터 j번째 문자까지 회문인지 체크하는 dp
  • dp2[i] = i번째 인덱스에서 분할 개수의 최솟값

 

dp[i][j]가 약간 이해가 안 갈 수 있는데, 예를 들어보자.

 

문자열 'BOTTOM' 에서 제일 앞의 인덱스를 1이라고 할 때, dp[1][6]은 false이고, dp[2][5]는 true, dp[3][4]도 true... 이렇게 볼 수 있다. 이를 어떻게 구현할까?

 

dp[i][j] 가 true이고, str[i - 1] == str[j + 1] 이라면, dp[i - 1][j + 1] 또한 true라는 점을 이용하여 dp 테이블을 Bottom-Up 방식으로 채울 수 있다.

 

마찬가지로 dp2를 구현하는 방법을 알아보자. idx번째 인덱스에서 다음과 같은 행동을 취할 수 있다. (idx = 현재 인덱스)

 

solve(idx) 에 대해 i = idx보다 크거나 같은 모든 인덱스일 때,

dp[idx][i] = true 라면, dp2[idx] = min(dp2[idx], solve(i + 1) + 1)

 

볼 수 있듯이 이는 Top-Down 방식으로 구현해야 한다. 이로써 모든 설명은 끝났다. 코드는 밑에 있다.

 

 

#include <iostream>
#include <string>

using namespace std;

bool dp[2501][2501];
int dp2[2501];

int sz; char str[2501];

int solve(int idx) {
    if (dp2[idx] != -1) return dp2[idx];
    int ans = 99996974;
    for (int i = idx; i <= sz; i++) {
        if (dp[idx][i]) ans = min(solve(i + 1) + 1, ans);
    }
    return dp2[idx] = ans;
}

int main() {

    string s; cin >> s;
    sz = s.size();
    for (int i = 0; i < sz; i++) {
        str[i + 1] = s[i];
    }

    str[sz + 1] = '0';
    for (int i = 1; i <= sz; i++) {
        dp[i][i] = true;
        if (str[i] == str[i + 1]) dp[i][i + 1] = true;
    }

    for (int i = 1; i <= sz; i++) {
        for (int j = 1; j <= sz; j++) {
            int s = i, r = j;
            while (str[s - 1] == str[r + 1] && dp[s][r]) {
                dp[s - 1][r + 1] = true;
                s--; r++;
            }
        }
    }

    for (int i = 1; i <= sz; i++) {
        dp2[i] = -1;
    }

    cout << solve(1) << endl;
}

 

 

난이도(객관적): Gold I

난이도(개인적): Gold I

'Problem Solving > Else' 카테고리의 다른 글

LIS 문제를 세그먼트 트리를 이용하여 풀이하는 방법  (0) 2022.04.06
BOJ 11570 : 환상의 듀엣  (0) 2022.04.06
BOJ 1949 : 우수 마을  (0) 2022.04.03
BOJ 4716 : 풍선  (0) 2022.04.02
BOJ 1826 : 연료 채우기  (0) 2022.03.28