본문 바로가기
Algorithm Study/BaekJoon (JAVA)

백준 12891_DNA 비밀번호_JAVA

by 창브로 2024. 3. 14.
728x90

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

 

12891번: DNA 비밀번호

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

www.acmicpc.net

 

처음 풀었던 시간초과 코드

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

public class Main {

    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[] charArr = br.readLine().toCharArray();

        int[] check = new int[4];

        st = new StringTokenizer(br.readLine());

        for(int i=0; i<4; i++) {
            check[i] = Integer.parseInt(st.nextToken());
        }

        int start = 0;
        int end = p-1;
        int count = 0;

        while (end<s) {
            int checkA = 0;
            int checkC = 0;
            int checkG = 0;
            int checkT = 0;

            for(int i=start; i<=end; i++) {
                if (charArr[i] == 'A') {
                    checkA += 1;
                } else if (charArr[i] == 'C') {
                    checkC += 1;
                } else if (charArr[i] == 'G') {
                    checkG += 1;
                } else if (charArr[i] == 'T') {
                    checkT += 1;
                }
            }
            if (checkA != check[0]) {
                start += 1;
                end += 1;
                continue;
            } else if (checkC != check[1]) {
                start += 1;
                end += 1;
                continue;
            } else if (checkG != check[2]) {
                start += 1;
                end += 1;
                continue;
            } else if (checkT != check[3]) {
                start += 1;
                end += 1;
                continue;
            }
            count += 1;
            start += 1;
            end += 1;
        }
        System.out.print(count);
    }
}

 

 

윈도우 슬라이드를 공부하고 수정한 코드

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

public class Main {
    static int[] myCheck;
    static int[] check;
    static int checkAnswer;
    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 배열

        check = new int[4]; // dna 조건 배열
        myCheck = new int[4]; // 지금 비밀번호 체크 배열
        checkAnswer = 0; // 4가지의 조건을 만족하는지 count하는 int
        int count = 0; // 정답 갯

        st = new StringTokenizer(br.readLine());

        // check 배열에 입력 받은 조건 대입
        for (int i = 0; i < 4; i++) {
            check[i] = Integer.parseInt(st.nextToken());
            if (check[i] == 0) {
                checkAnswer++;
            }
        }

        // 제일 처음부터 부분집합 갯수까지 알파벳 세기
        for (int i = 0; i < P; i++) {
            Add(dna[i]);
        }

        if (checkAnswer == 4) {
            count++;
        }

        // 윈도우 슬라이딩
        for (int i = P; i<S; i++) {
            int j = i-P; // j가 부분집합의 가장 처음 단어, i가 부분집합이 끝나고 가장 처음 단어
            Add(dna[i]); // i를 추가하고 계산
            Remove(dna[j]); // j를 빼주고 계산

            if (checkAnswer==4) {
                count++;
            }
        }

        System.out.print(count);
        br.close();
    }

    private static void Add(char c) {
        switch(c) {
            case 'A':
                myCheck[0]++;
                if (myCheck[0] == check[0]) {
                    checkAnswer++;
                }
                break;
            case 'C':
                myCheck[1]++;
                if (myCheck[1] == check[1]) {
                    checkAnswer++;
                }
                break;
            case 'G':
                myCheck[2]++;
                if (myCheck[2] == check[2]) {
                    checkAnswer++;
                }
                break;
            case 'T':
                myCheck[3]++;
                if (myCheck[3] == check[3]) {
                    checkAnswer++;
                }
                break;
        }
    }

    private static void Remove(char c) {
        switch(c) {
            case 'A':
                // 빼기 전 상황에서 두가지의 check가 같으면
                // 조건이 성립하지 않기 때문에 checkAnswer을 하나 빼준다
                if (myCheck[0] == check[0]) {
                    checkAnswer--;
                }
                myCheck[0]--;
                break;
            case 'C':
                if (myCheck[1] == check[1]) {
                    checkAnswer--;
                }
                myCheck[1]--;
                break;
            case 'G':
                if (myCheck[2] == check[2]) {
                    checkAnswer--;
                }
                myCheck[2]--;
                break;
            case 'T':
                if (myCheck[3] == check[3]) {
                    checkAnswer--;
                }
                myCheck[3]--;
                break;
        }
    }
}

 

 

 

회고

- 윈도우 슬라이드 코드 짜기가 너무 생소해서 2시간은 잡고 있었던 것 같지만 결국 이해하고 해결해서 다행이다.

'Algorithm Study > BaekJoon (JAVA)' 카테고리의 다른 글

백준 2164_카드2_JAVA  (0) 2024.03.15
백준 1874_스택 수열_JAVA  (1) 2024.03.15
백준 1940_주몽_JAVA  (1) 2024.03.14
백준 2018_수들의 합 5_JAVA  (0) 2024.03.14
백준 11659_구간 합 구하기 4_JAVA  (0) 2024.03.14