어흥

[백준 2079, 1509] 팰린드롬 / 팰린드롬 분할 (C++) 본문

알고리즘/백준

[백준 2079, 1509] 팰린드롬 / 팰린드롬 분할 (C++)

라이언납시오 2020. 3. 17. 15:11
728x90
반응형

[팰린드롬] 문제 링크: https://www.acmicpc.net/problem/2079

 

2079번: 팰린드롬

문제 팰린드롬(palindrome)이란 앞에서부터 읽으나 뒤에서부터 읽으나 같은 단어를 말한다. 'aba'나 'a'와 같은 단어는 팰린드롬이며, 'abaccbcb'나 'anavolimilana'와 같은 단어는 팰린드롬이 아니다. 만일 어떤 단어가 팰린드롬이 아니라면, 그 단어는 여러 개의 팰린드롬으로 나누어질 수 있을 것이다. 단어가 주어졌을 때 이를 여러 개의 팰린드롬으로 나누되, 나누어진 팰린드롬의 개수가 최소가 되도록 나누려고 한다. 예를 들어 ab

www.acmicpc.net

[팰린드롬 분할]문제 링크: 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

1. 주의할 점

- 두 문제 모두 최소의 팰린드롬 수를 구하는 문제지만 문자열의 길이가 다르다.

- 각 부분 문자열마다 비교할 때(구현 과정) 헷갈릴 수 있다.

 

2. 구현

- 길이가 1인 문자열 혹은 부분 문자열은 항상 펠린드롬이다 -> DP[i][i] = True

- 길이가 2인 문자열 혹은 부분 문자열은 오른쪽과 비교해서 같으면 펠린드롬이다 if(Str[i]==Str[i+1]) DP[i][i+1] = DP[i+1][i] = True

- 이 문제의 경우 2개의 배열 DP[][], Result[]가 필요하다.

DP[i][j] : Str[i] ~ Str[j]의 부분문자열이 팰린드롬인지 아닌지 알려주는 Boolean 배열

Result[i] : Str[1]~Str[i]의 부분문자열에 존재하는 최소 팰린드롬 개수

- Palindrome 함수:  문자열의 양옆 글자가 같고, 양옆 글자를 제외한 부분문자열이 팰린드롬이라면 해당 문자열은 팰린드롬이다

Ex) Str = "4321234"

양 끝 문자 : '4' == '4'    -> 같다

양 끝을 제외한 부분 문자열 = "32123"    -> 팰린드롬이다

결론: Str은 팰린드롬이다

- 이후 Result의 1번째 Index에서 Str의 길이까지 Result배열을 비교하면서 Result[Index]가 0이거나(아직 비교를 안한 경우), Result[Index] > Result[Index-1]+1를 만족하는 경우(현재 저장된 값보다 더 개수의 펠린드롬으로 Str[1]~Str[Index]까지의 문자열을 만들 수 있는 경우) Result[Index] = Result[Index]+1로 설정한다.

 

#include <iostream>
#include <string>
using namespace std;
bool dp[2501][2501] = { false, };
int result[2501];
string str;

void palindrome() {
	for (int i = 2; i < str.size(); i++) 
		for (int j = 1; j < str.size() - i; j++) 
			if (str[j] == str[j + i] && dp[j + 1][j + i - 1]) 
				dp[j][j + i] = dp[j + i][j] = true;	
}

int main() {
	cin >> str;
	str = " " + str;
	//길이 1개짜리는 항상 펠린드롬
	for (int i = 1; i <= str.size(); i++) 
		dp[i][i] = true;
	//바로 옆에 칸과 같다면 펠린드롬
	for (int i = 1; i < str.size(); i++) {
		if (str[i] == str[i + 1]) {
			dp[i][i + 1] = true;
			dp[i + 1][i] = true;
		}
	}
	palindrome();
	for (int i = 1; i <= str.size(); i++) {
		for (int j = 1; j <= i; j++) {
			if (dp[i][j]) {
				if (result[i] == 0 || result[i] > result[j - 1] + 1)
					result[i] = result[j - 1] + 1;
			}
		}
	}
	cout << result[str.size()-1];
	system("pause");
	return 0;
}
728x90
반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준 2573] 빙산 (C++)  (0) 2020.03.18
[백준 7348] 테이블 옮기기 (C++)  (0) 2020.03.18
[백준 1167] 트리의 지름 (C++)  (0) 2020.03.16
[백준 14405] 피카츄 (C++)  (0) 2020.03.16
[백준 2151] 거울 설치 (C++)  (0) 2020.03.16
Comments