[알고리즘] 12891. DNA 비밀번호

2024. 2. 3. 20:40Algorithm/with Java

0. 문제

 

 

12891번: DNA 비밀번호

평소에 문자열을 가지고 노는 것을 좋아하는 민호는 DNA 문자열을 알게 되었다. DNA 문자열은 모든 문자열에 등장하는 문자가 {‘A’, ‘C’, ‘G’, ‘T’} 인 문자열을 말한다. 예를 들어 “ACKA”

www.acmicpc.net

 


1. 문제 이해

 

수학 잘 못함.

 


2. 제출

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

/**
 * BOJ12891
 */
public class Main {

    static int ret;
    static int[] cond, cnt; // 조건, 문자 카운팅
    static final int A=0, C=1, G=2, T=3;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        ret = 0;
        int S = Integer.parseInt(st.nextToken());
        int P = Integer.parseInt(st.nextToken());

        // 문자열
        st = new StringTokenizer(br.readLine());
        char[] arr = st.nextToken().toCharArray();

        // 부분문자열 조건
        st = new StringTokenizer(br.readLine());
        cond = new int[4]; // condition
        for(int i=0; i<4; i++){
            cond[i] = Integer.parseInt(st.nextToken());
        }

        //슬라이딩 윈도우 생성
        cnt = new int[4];
        for(int i=0; i<P; i++){
            switch (arr[i]) {
                case 'A':
                    cnt[A]++;       
                    break;
                case 'C':
                    cnt[C]++;
                    break;
                case 'G':
                    cnt[G]++;
                    break;
                case 'T':
                    cnt[T]++;
                    break;
            }
        }
        check();

        //윈도우 이동
        int limit = S-P+1;
        for(int i=1; i<limit; i++){
            char out = arr[i-1]; // 나간것
            switch (out) {
                case 'A':
                    cnt[A]--;       
                    break;
                case 'C':
                    cnt[C]--;
                    break;
                case 'G':
                    cnt[G]--;
                    break;
                case 'T':
                    cnt[T]--;
                    break;
            }
            char in =  arr[i+P-1]; // 들어온것
            switch (in) {
                case 'A':
                    cnt[A]++;       
                    break;
                case 'C':
                    cnt[C]++;
                    break;
                case 'G':
                    cnt[G]++;
                    break;
                case 'T':
                    cnt[T]++;
                    break;
            }
            check();
        }

        System.out.println(ret);
    }

    public static void check(){
        // 조건을 만족하는지 확인
        // System.out.println("cond : " + Arrays.toString(cond));
        // System.out.println("cnt : " + Arrays.toString(cnt));
        for(int i=0; i<4; i++){
            if(cnt[i] < cond[i]) return;
        }
        ret++;
    }
}

조건을 만족하는 부분 순열을 구하는 문제다.

 

매번 문자열을 새로 카운팅하면 시간을 초과한다.

 

슬라이딩 원도우를 사용해서 나가는 것과 들어오는 것만 체크한다.

 


'Algorithm > with Java' 카테고리의 다른 글

[Java] 연결 리스트  (0) 2024.02.18
[Java] Heap  (0) 2024.02.18
[알고리즘] 11723. 집합  (0) 2024.02.03
[알고리즘] 2023. 신기한 소수  (0) 2024.02.03
[Java] Stack, Queue, Priority Queue  (0) 2024.02.03