우보천리 개발

[백준12891] DNA 비밀번호 Java 본문

알고리즘/Do it! 알고리즘 코딩테스트

[백준12891] DNA 비밀번호 Java

밥은답 2023. 8. 14. 21:01
반응형

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

 

12891번: DNA 비밀번호

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

www.acmicpc.net

 

package Chapter1;

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

public class BJ12891 {
    static int[] required = new int[4]; // 필수로 있어야 하는 개수
    static int[] passCheck = new int[4]; // 현재 내가 갖고 있는 개수
    static int counter; // 4개면 비번 생성 가능

    public static void main(String[] args) throws IOException {
        // 입력
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int s = Integer.parseInt(st.nextToken()); // 문자열 길이
        int p = Integer.parseInt(st.nextToken()); // 부분 문자열 길이
        char[] dna = br.readLine().toCharArray(); // DNA 문자열
        st = new StringTokenizer(br.readLine());

        int answer = 0;

        // 처음 필수 개수 조합
        for (int i=0; i<4; i++) {
            // {A C G T}
            required[i] = Integer.parseInt(st.nextToken());
            // 0이면, 0개이상이라는 뜻. 즉 다 됨. 그래서 카운터 1개 올림
            if (required[i] == 0) counter++;
        }

        // 초기 P길이만큼의 문자열에 대해 비밀번호 처리
        for (int i=0; i<p; i++) {
            addCharacter(dna[i]);
        }

        // 첫 윈도우에서 비밀번호 될 수 있는지 확인
        if (counter == 4) answer++;

        // 윈도우 크기만큼 다음 알파벳 더해주고 해당 윈도우의 첫번째였던 알파벳 제거
        for (int i=p; i<s; i++) {
            int j = i-p;
            addCharacter(dna[i]);
            removeCharacter(dna[j]);
            if (counter == 4) answer++;
        }

        System.out.println(answer);

    }

    private static void removeCharacter (char c) {
        switch (c) {
            case 'A':
                checkIfSameRemove(0);
                passCheck[0]--;
                break;
            case 'C':
                checkIfSameRemove(1);
                passCheck[1]--;
                break;
            case 'G':
                checkIfSameRemove(2);
                passCheck[2]--;
                break;
            case 'T':
                checkIfSameRemove(3);
                passCheck[3]--;
                break;
        }
    }

    private static void addCharacter (char c) {
        /**
         * 해당 알파벳의 배열 카운트를 올려주고, 개수 이상이지만 같을 때 딱 한번 체크하면
         * 그 이상도 해당 된다는 것이기에 checkIfSame(idx)로 확인해줌
         * */
        switch (c) {
            case 'A':
                passCheck[0]++;
                checkIfSame(0);
                break;
            case 'C':
                passCheck[1]++;
                checkIfSame(1);
                break;
            case 'G':
                passCheck[2]++;
                checkIfSame(2);
                break;
            case 'T':
                passCheck[3]++;
                checkIfSame(3);
                break;
        }
    }

    private static void checkIfSame(int idx) {
        if (passCheck[idx] == required[idx]) counter++;
    }

    private static void checkIfSameRemove(int idx) {
        if (passCheck[idx] == required[idx]) counter--;
    }
}
반응형
Comments