- Today
- Yesterday
- Total
메이쁘
(JAVA) 백준 1509번 : 팰린드롬 분할 본문
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
팰린드롬 문제 중 꽤 어려운 문제이다.
*** 팰린드롬 유사 문제
(JAVA) 백준 10942번 : 팰린드롬?
https://www.acmicpc.net/problem/10942 10942번: 팰린드롬? 총 M개의 줄에 걸쳐 홍준이의 질문에 대한 명우의 답을 입력으로 주어진 순서에 따라서 출력한다. 팰린드롬인 경우에는 1, 아닌 경우에는 0을 출력�
maivve.tistory.com
(JAVA) 백준 9933번 : 민균이의 비밀번호
https://www.acmicpc.net/problem/9933 9933번: 민균이의 비밀번호 문제 창영이는 민균이의 컴퓨터를 해킹해 텍스트 파일 하나를 자신의 메일로 전송했다. 파일에는 단어가 한 줄에 하나씩 적혀있었고, 이 ��
maivve.tistory.com
팰린드롬이란
앞뒤가 똑같은 전화번호 단어 이다.
즉, 앞에서부터 보나 뒤에서부터 보나 똑같은 단어라는 뜻이다.
1 또는 121 또는 1221 이 팰린드롬에 해당한다.
단어 길이가 1인 경우에는 무조건 팰린드롬이고,
단어 길이가 2인 경우에는 두 문자가 같아야지 팰린드롬이고,
단어 길이가 3 이상인 경우에는
1) 양 끝의 두 문자가 같고,
2) 양 끝의 두 문자를 제외하고 안에 있는 단어가 팰린드롬이면
팰린드롬이다.
그런데 문제는
해당 문자열 중 팰린드롬 들로 분리했을 때
그 개수가 가장 작은 값을 찾는 것이다.
그렇기 때문에 DP(동적 프로그래밍)을 사용해서 최소값을 찾아내야 한다.
위 규칙을 가진 별도의 함수를 통해
2차원 boolean 배열에 팰린드롬 여부를 T/F로 저장한다.
핵심
boolean[y][x] : y ~ x 인덱스 내 문자열의 팰린드롬 여부
DP[i] : 0(시작) ~ i 까지의 문자들로 이루어진 문자열이 가지는 팰린드롬 개수의 최소값.
*** 중요
DP[i] = Math.min(DP[i], DP[j - 1] + 1)
-> i는 1(첫 번째 문자 인덱스) ~ i번째 문자 인덱스 까지의 문자열을 나타냄. i 는 최대 n까지 가능
-> j 또한 1(첫 번째 문자 인덱스) ~ i번째 문자 인덱스 까지의 문자열을 나타냄. 이 때, j는 항상 최대 i까지 가능

이를 보면
n개의 문자를 가진 문자열이 존재할 때
j <= i 이고,
i <= n 이다.
그래서 2중 for문으로 i와 j를 돌리는데,
boolean[y][x](= 팰린드롬 여부) 를 사용해서 j ~ i 사이 문자열은 팰린드롬인지 아닌지 판단해서
팰린드롬인 경우만 놓고 DP를 얻는다.
boolean[j][i] 가 true인 경우에는
j 인덱스부터 i 인덱스의 문자열의 팰린드롬 최소 개수는 항상 1이므로
1 인덱스부터 i 인덱스의 문자열의 기존 팰린드롬 최소 개수보다
1 ~ j - 1 인덱스의 문자열의 팰린드롬 최소 개수 + 1 보다 작다면 DP[i] 값을 이 값으로 갱신한다.
*** +1을 하는 이유는 문자 하나가 추가되었기 때문에, 문자 하나는 팰린드롬 1개라고 볼 수 있기 때문이다.
설명이 조금 부족한 것 같습니다..ㅠㅠㅠ
남은 부분은 소스코드를 참고해주시면 감사하겠습니다!
질문도 받아욥!!
항상 방문해주신 분들에게 감사드립니다 :)
소스코드
import java.io.BufferedReader; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
// 백준 1509번 : 팰린드롬 분할 | |
// 동적 프로그래밍 문제 | |
public class p1509 { | |
static String str; | |
static char[] strCharArr; | |
static boolean[][] palindromes; | |
static int[] dp; | |
public static void main(String args[]) throws IOException { | |
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | |
str = br.readLine(); | |
strCharArr = str.toCharArray(); // 사용 인덱스 : 0 ~ n - 1 | |
int n = str.length(); | |
palindromes = new boolean[n + 1][n + 1]; // 사용 인덱스 : 1 ~ n | |
dp = new int[n + 1]; // 사용 인덱스 : 1 ~ n | |
// 팰린드롬 설정 | |
setPalindromes(n); | |
palindrome(n); | |
System.out.println(dp[n]); | |
} | |
// 팰린드롬 | |
// DP[i] => Math.min(DP[i], DP[j - 1] + 1) | |
// DP[i] => 0 ~ i - 1 번째까지의 문자들 중 팰린드롬 분할 최소 개수 | |
// j ~ i 인덱스까지 문자들의 분할 최소 개수 : DP | |
static void palindrome(int n) { | |
for(int i = 1; i <= n; i++) { | |
for(int j = 1; j <= i; j++) { | |
if(palindromes[j][i]) { | |
// 여기서 dp[i] == 0 인 경우에는 아직 해당 문자열을 탐색한 경우가 없다는 뜻으로 초기 설정이 필요하다. | |
if(dp[i] > dp[j - 1] + 1 || dp[i] == 0) { | |
dp[i] = dp[j - 1] + 1; | |
} | |
} | |
} | |
} | |
} | |
// DP를 활용한 풀이 방법 | |
private static void setPalindromes(int n) { | |
for(int i = 1; i <= n; i++) { | |
// S ~ E의 길이가 1일 때(즉, 한 개의 수만 선택했을 때) 무조건 팰린드롬 | |
palindromes[i][i] = true; | |
// S ~ E의 길이가 2일 때(즉, 두 개의 수만 선택했을 때) | |
if(i < n) { | |
if(strCharArr[i - 1] == strCharArr[i]) { | |
palindromes[i][i + 1] = true; | |
palindromes[i + 1][i] = true; | |
} | |
} | |
} | |
// S ~ E의 길이가 3 이상일 때 | |
// 1) 양 끝의 숫자가 같고, 2) 남은 안의 숫자들이 팰린드롬이면 이 길이의 숫자들도 팰린드롬이다. | |
for(int i = 3; i <= n; i++) { // i는 S ~ E의 길이. 최소가 3이므로 3부터 시작. = 끝 인덱스 | |
for(int j = 1; j < n - i + 1; j++) { // i 만큼의 길이를 보고 팰린드롬을 찾기 위한 시작 인덱스. | |
int k = j + i - 1; | |
if(strCharArr[j - 1] == strCharArr[k - 1]) { // 1)의 조건. | |
if(palindromes[j + 1][k - 1]) { // 2)의 조건. | |
palindromes[j][k] = true; | |
palindromes[k][j] = true; | |
} | |
} | |
} | |
} | |
} | |
} |
'Algorithm > Baekjoon' 카테고리의 다른 글
(JAVA) 백준 2146번 : 다리 만들기 (0) | 2020.05.22 |
---|---|
(JAVA) 백준 1439번 : 뒤집기 (0) | 2020.05.22 |
(JAVA) 백준 2810번 : 컵홀더 (2) | 2020.05.19 |
(JAVA) 백준 11586번 : 지영 공주님의 마법 거울 (0) | 2020.05.19 |
(JAVA) 백준 14502번 : 연구소 (0) | 2020.05.16 |