[C++] 백준 2079 [팰린드롬]

date:

Updated:


Categories:

Tags: , ,

접근방식

DP로 접근하면 되는 문제이다.
백준 10942와 연관된 문제이다.

풀이방법

anavolimilana 라는 문자열가 있다고 생각해보자.
이 문자를 팰린드롬으로 나누려면 처음 인덱스부터 팰린드롬이 되는 인덱스를 찾아줘야한다.
그 이후 재귀적으로 계속 줄여나가서 마지막 인덱스까지 모두 탐색하면 된다.

count_pal(string s, int count) 라는 함수가 있다고 하자. 이 함수는 s라는 문자열 안의 팰린드롬의 최소 갯수를 찾아주는 함수이다.
count_pal(anavolimailana, 0) 이 초기상태이고, a는 팰린드롬이기 때문에 count_pal(anavolimailana, 0) = count_pal(navolimailana, 1)로 나타낼 수 있다.

또한 ana도 팰린드롬이기 때문에, count_pal(anavolimailana, 0) = count_pal(volimailana, 1)로 나타낼 수 있다.
이 과정에서 중복되는 부분 문제가 생기기 때문에 DP로 해결해야한다.

이해하기 쉽게 count_pal의 매개변수를 string으로 정의해놨지만, 실제로는 인덱스를 매개변수로 하는 함수를 작성 할 것이다.

점화식 작성

일단, 백준 10942를 참고해서 is_pal()이라는 팰린드롬 판별 함수를 작성한다.
그 이후에 count_pal()이라는 팰린드롬의 최소 갯수를 나타내는 함수를 작성하면 된다.

count_pal(int start) = 문제에서 주어진 문자열의 start 인덱스부터 팰린드롬 문자열의 갯수이다.

count_pal()의 점화식은 다음과 같다.

for(int i=0; i<e-start+1; i++){
	if(is_pal(start, start+i)){
		ret = min(ret, count_pal(start+i+1)+1);
	}
}

여기서 e는 주어진 부분 문자열의 마지막 인덱스, start는 첫 인덱스이다.
첫 문자부터 마지막 문자까지 순회하면서 팰린드롬이 문자열을 찾으면 첫 인덱스를 찾은 문자열의 끝 인덱스+1로 옮겨서 다시 탐색하는 방법이다.

점화식의 초기조건

주어진 문자열의 마지막 문자까지 확인하고 나면 그 다음 인덱스로 count_pal이 호출된다. 그 때의 start는 e보다 크므로, 초기조건은

if(start > e) return 0;

로 정해주면 된다.

소스코드

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

int pal[2001][2001];
int cache[2001];
string s;
int e;
const int MAX = 987654321;

bool is_pal(int st, int e){
    if(st >= e) return true;
    int& ret = pal[st][e];
    if(ret == -1){
        ret = ((s[st] == s[e]) && is_pal(st+1, e-1));
    }
    return ret;
}

int count_pal(int start){
    if(start > e) return 0;
    int& ret = cache[start];
    if(ret == MAX){
        for(int i=0; i<e-start+1; i++){
            if(is_pal(start, start+i)){
                ret = min(ret, count_pal(start+i+1)+1);
            }
        }
    }
    return ret;
}

int main(){
    int result = MAX;
    for(int i=0; i<2001; i++){
        for(int j=0; j<2001; j++){
            pal[i][j] = -1;
            cache[i] = MAX;
        }
    }
    cin >> s;
    e = s.size()-1;
    cout << count_pal(0);
}

Leave a comment