반응형

https://www.acmicpc.net/problem/1509

 

1509번: 팰린드롬 분할

세준이는 어떤 문자열을 팰린드롬으로 분할하려고 한다. 예를 들어, ABACABA를 팰린드롬으로 분할하면, {A, B, A, C, A, B, A}, {A, BACAB, A}, {ABA, C, ABA}, {ABACABA}등이 있다. 분할의 개수의 최솟값을 출력하

www.acmicpc.net

 

 

[ 문제풀이 ]

 

먼저 dp라는 이차원 배열을 만들어서 팰린드롬인지 체크를 해야 합니다. dp [1][3]이 1이라면 문자열의 1번부터 3번까지는 팰린드롬이라는 뜻입니다.

 

그리고 어디부터 어디까지 팰린드롬인지 체크하기 위해서는 문자열의 끝에서부터 시작해야합니다.

 

먼저 글자가 하나일 때는 모든 글자가 팰린드롬이므로 dp [i][i]는 1로 채워줍니다.

 

그러고 나서 4번째 행부터 체크를 시작합니다. 나의 바로 앞까지 만약 팰린드롬인 문자열이 있다면 나와 팰린드롬인 문자열의 바로 앞 문자와 비교해서 같으면 나도 팰린드롬이라는 결과를 얻을 수 있습니다.

 

즉, dp [i+1][j-1]이 1이라면 i번째 문자열과 j번째 문자열이 같다면 dp [i][j]는 1이 됩니다.

 

이렇게 모든 dp배열을 채우면 몇 번 문자부터 몇번 문자까지 팰린드롬인지 모두 체크할 수 있고, 이것을 이용해서 팰린드롬을 최소 몇 개로 나타낼 수 있는지 구할 수 있습니다.

 

이번엔 반대로 앞에서부터 시작합니다.

 

ans배열을 만들고, 기록을 시작합니다. ans배열은 i번째 문자열까지 팰린드롬을 최소로 나눌 수 있는 수를 기록할 배열입니다.

 

만약 ans [i]의 값을 구하고 싶다면 j번부터 i번까지 팰린드롬인 문자열을 찾고, 만약 팰린드롬이라면 ans [i] 값과 ans [j-1]+1의 값을 비교해 더 작은 숫자를 대입해 줍니다. 왜냐하면 ans [j-1]은 j-1번째 문자열까지의 최솟값을 저장했기 때문입니다.

 

[ 소스 코드 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <string>
 
using namespace std;
 
string str;
 
int dp[2501][2501];                    //팰린드롬인지 판별할 배열
int ans[2501];                        //최솟값을 저장할 배열
 
int main()
{
    cin >> str;
    str = ' ' + str;
    for (int i = str.size(); i >= 1; i--) {        //dp[start][end] start부터 end까지 팰린드롬이라면 1 아니라면 0
        for (int j = str.size(); j >= i; j--) {
            if (i == j) dp[i][j] = 1;
            else if (j - i == 1) {
                if (str[i] == str[j]) {
                    dp[i][j] = 1;
                }
            }
            else {
                if (dp[i + 1][j - 1== 1) {
                    if (str[i] == str[j]) {
                        dp[i][j] = 1;
                    }
                }
            }
        }
    }
 
    for (int i = 1; i <= str.size()-1; i++) {
        ans[i] = 3000;
        for (int j = 1; j <= i; j++) {
            if (dp[j][i] == 1) {                //j부터 i까지 팰린드롬이라면 j-1의 값보다 1 더 크므로
                ans[i] = min(ans[i], ans[j - 1+ 1);
            }                                    //하지만 갱신이 되어있는 값이 더 작을 수도 있으므로
        }                                        //둘을 비교해서 더 작은 값을 대입
    }
 
 
    cout << ans[str.size()-1];
}
cs
반응형

+ Recent posts