티스토리 뷰

알고리즘/백준

백준 2306 (유전자) - java

김다미김태리신시아 2024. 7. 7. 20:54

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

 

문제

DNA 서열은 4개의 문자 {a,c,g,t} 로 이루어진 문자열이다. DNA 서열에는 생명의 신비를 풀 수 있는 많은 정보가 들어 있다. 특히 KOI 유전자의 길이는 사람의 키와 깊은 상관 관계가 있다는 것이 알려져 있다. 이러한 KOI 유전자는 다음의 조건을 만족한다.

  1. at 와 gc 는 가장 짧은 길이의 KOI 유전자이다.
  2. 어떤 X가 KOI 유전자라면, aXt와 gXc도 KOI 유전자이다. 예를 들어, agct 와 gaattc는 KOI 유전자이나, tgca 와 cgattc는 KOI 유전자가 아니다.
  3. 어떤 X와 Y가 KOI 유전자라면, 이 둘을 연결한 XY도 KOI 유전자이다. 예를 들면, aattgc 또는 atat는 KOI 유전자이나 atcg 또는 tata는 KOI 유전자가 아니다.

KOI 유전자는 DNA 서열 중에서 부분 서열로 구성되어 있다. 부분 서열이란 주어진 서열에서 임의의 위치에 있는 0개 이상의 문자들을 삭제해서 얻어지는 서열이다. 예를 들면, DNA 서열 acattgatcg에서 두 번째 문자 c와 마지막 문자 g를 삭제하여 생긴 부분 서열 aattgatc는 길이가 8인 KOI 유전자이다. 그러나 마지막 문자 g를 삭제하여 만들어진 부분 서열 acattgatc는 KOI 유전자가 아니다.

문제는 주어진 DNA 서열의 부분 서열들 중에서 길이가 최대가 되는 KOI 유전자를 찾아 그 길이를 출력하는 것이다.

 

유형 : 다이나믹 프로그래밍

 

접근 방식

  • 우선 최소 길이가 2이기 때문에 배열을 순회하면서 "at" , "gc"를 만족하는 경우 dp배열을 2로 초기화한다.
  • dp 배열을 다음으로 구하는 것은 다음과 같다
    • 시작 지점과 끝 지점이 "at", "gc"를 만족시키는 경우 2 + (시작 지점 + 1 , 끝 지점 -1) 길이
    • 위 조건을 무시하고 단순히 배열의 최댓값
  • 위 2조건의 최댓값을 구하면 된다.

 

전체 코드

import java.util.*;
import java.io.*;

public class Main {

    static char[] chars;
    static int n;
    static String arr;
    static int[][] dp;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        arr = br.readLine();
        chars = arr.toCharArray();
        n = arr.length();

        dp = new int[n+1][n+1];

        String tmp;


        int result = 0;

        for(int i = 0 ; i < n - 1 ; i++) {
            tmp = arr.substring(i,i+2);

            if(tmp.equals("at") || tmp.equals("gc")) {
                dp[i][i+1] = 2;

                result = 2;
            }
        }

        for(int k = 2; k < n ; k++) {
            for(int i = 0 ; i < n - k ; i++) {
                int len = i + k;

                int semiLen = 0;

                if(chars[i] == 'a' && chars[i+k] == 't')
                    semiLen = 2;

                if(chars[i] == 'g' && chars[i+k] == 'c')
                    semiLen = 2;


                dp[i][len] = Math.max(dp[i][len],dp[i+1][len - 1] + semiLen);


                for(int j = i ; j < len ;j++) {
                    dp[i][len] = Math.max(dp[i][len], dp[i][j] + dp[j+1][len]);
                }

                result = Math.max(result,dp[i][len]);
            }
        }


        System.out.println(result);
        br.close();
    }
}

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

백준 24888 (노트 조각) - java  (2) 2024.09.22
백준 15906 (변신 이동 게임) - java  (0) 2024.07.14
백준 16681 (등산) - java  (0) 2024.06.28
백준 16472 (고냥이) - java  (0) 2024.06.27
백준 30024 (옥수수밭) - java  (0) 2024.06.20