<aside> 💡 슬라이딩 윈도우 알고리즘은 2개의 포인터로 범위를 지정한 다음 **범위(window)를 유지한 채로 이동(sliding)**하며 문제를 해결한다. 투 포인터 알고리즘과 매우 비슷하고 원리도 간단.

</aside>

1. DNA 비밀번호

1.1. 문제 설명

Untitled

Untitled

Untitled

**[A, C, G, T]**  
 1  0  0  1   **A와 T가 들어있어야 함.**
**GATA**
GA -> X
AT -> O
TA -> O

1.2. 문제 분석

Untitled

Untitled

Untitled

Untitled

<aside> 💡 업데이트할 때 빠지는 문자열, 신규 문자열만 보고 업데이트 하는 방식이 무슨 말이냐면, [C, C , T, G, G, A, T, T, G] 배열에서 C는 빠지고 G가 추가되는 것을 의미함. 이렇게 되면 중간에 있는 문자열들이 아무리 길어도 상관이 없다. (이전에도 있었기 때문)

</aside>

1.3. 슈도코드

Untitled

1.4. 구현

public class DNA_12891 {
    static int[] myArr = new int[4]; // {0,0,0,0};
    static int[] ACGT = new int[4]; //{2,0,1,1};
    static int checkSecret = 0; // 만족하는 수. 4개가 만족해야 함
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer tokenizer = new StringTokenizer(bufferedReader.readLine());
        int S = Integer.parseInt(tokenizer.nextToken()); // 문자열 길이
        int P = Integer.parseInt(tokenizer.nextToken()); // 부분 문자열 길이
        int result = 0;
        char[] sArr = new char[S]; // 처음에 들어오는 전체 문자열

        // 데이터 입력 부분
        sArr = bufferedReader.readLine().toCharArray();
        tokenizer = new StringTokenizer(bufferedReader.readLine());
        for(int i=0; i < 4; i++) {
            ACGT[i] = Integer.parseInt(tokenizer.nextToken());
            
            // 0인 경우에는 무시해도 됨. (checkSecret++)
            if(ACGT[i] == 0) {
                checkSecret++;
            }
        }

        // 부분 문자열 처음 받을 때 셋팅 (전체 중 첫 번째 슬라이드)
        for(int i=0; i < P; i++) {
            add(sArr[i]);
        }

        if(checkSecret == 4) {
            result++;
        }

        // 슬라이딩 윈도우. 여기부터는 오른쪽으로 한 칸 이동한 부분부터 처리를 함.
        for(int i=P; i < S; i++) {
            int j = i-P; // 8-8, 9-8, 10-8...범위를 유지하면서 이동함.
            // 한칸씩 이동할 때 빠지는 애와 들어가는 애만 체크하면 됨.
            add(sArr[i]); // 새로 들어가는 부분
            remove(sArr[j]); // 빠지는 부분
            if(checkSecret == 4) {
                result++;
            }
        }

        System.out.println(result);
    }

    private static void remove(char c) {
        switch (c) {
            case 'A':
                if(myArr[0] == ACGT[0])
                    checkSecret--;
                myArr[0]--;
                break;
            case 'C':
                if(myArr[1] == ACGT[1])
                    checkSecret--;
                myArr[1]--;
                break;
            case 'G':
                if(myArr[2] == ACGT[2])
                    checkSecret--;
                myArr[2]--;
                break;
            case 'T':
                if(myArr[3] == ACGT[3])
                    checkSecret--;
                myArr[3]--;
                break;
        }
    }

    private static void add(char c) {
        switch (c) {
            case 'A':
                myArr[0]++;
                if(myArr[0] == ACGT[0])
                    checkSecret++;
                break;
            case 'C':
                myArr[1]++;
                if(myArr[1] == ACGT[1])
                    checkSecret++;
                break;
            case 'G':
                myArr[2]++;
                if(myArr[2] == ACGT[2])
                    checkSecret++;
                break;
            case 'T':
                myArr[3]++;
                if(myArr[3] == ACGT[3])
                    checkSecret++;
                break;
        }
    }
}