![[Java] 백준 12891번 문제(DNA 비밀번호)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk4qQd%2FbtsMMc0396h%2FOeE1pZSL9lTWFQYsbm2crK%2Fimg.png)
[Java] 백준 12891번 문제(DNA 비밀번호)자료구조 & 알고리즘/BOJ2025. 3. 17. 15:37
Table of Contents
원본 링크 : https://www.acmicpc.net/problem/12891
문제설명
소스코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Boj_12891
{
static int[] inputACGT = new int[4]; // 입력 받은 부분문자열에 포함되어야 할 최소 개수
static int[] countACGT = new int[4]; // 구간에 포함된 부분문자열에 포함된 개수
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int count = 0; // 정답을 저장하는 변수
// n과 m을 받아옴
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
// 문자열을 받아옴
char[] str = br.readLine().toCharArray();
// 입력 받은 부분문자열에 포함되어야 할 최소 개수를 받아옴
st = new StringTokenizer(br.readLine());
for (int i = 0; i < inputACGT.length; i++) inputACGT[i] = Integer.parseInt(st.nextToken());
// 초기 윈도우 구성
for (int i = 0; i < m; ++i) add(str[i]);
if (check()) ++count;
// 슬라이딩 윈도우
for (int startPtr = 0; startPtr < n - m; ++startPtr)
{
int endPtr = startPtr + m;
remove(str[startPtr]); // str의 앞 문자열을 제거
add(str[endPtr]); // str의 뒷 문자열을 추가
if (check()) ++count;
}
System.out.println(count);
}
static void add(char c)
{
if (c == 'A') ++countACGT[0];
else if (c == 'C') ++countACGT[1];
else if (c == 'G') ++countACGT[2];
else ++countACGT[3];
}
static void remove(char c)
{
if (c == 'A') --countACGT[0];
else if (c == 'C') --countACGT[1];
else if (c == 'G') --countACGT[2];
else --countACGT[3];
}
static boolean check()
{
for (int i = 0; i < 4; ++i) if (countACGT[i] < inputACGT[i]) return false;
return true;
}
}
설명
이 예시로 그림으로 표현하면
inputACGT는 입력 받은 부분문자열에 포함되어야할 최소 개수이다.
초기 윈도우 구성을 마치면 countACGT는 현재까지 윈도우에서 각 알파벳의 출현 숫자를 기록한 배열이고, 아래와 같다.
잊지말아야할 것은 초기 윈도우를 구성하고 check 메서드를 통해서 현재까지 부분 문자열은 문제없는지 검사해야한다.
static boolean check()
{
for (int i = 0; i < 4; ++i) if (countACGT[i] < inputACGT[i]) return false;
return true;
}
슬라이딩 윈도우 for문을 살펴보면 아래와 같다.
여기서 startPtr의 값을 빼주고(remove) endPtr의 값을 추가(add)해준다.
static void add(char c)
{
if (c == 'A') ++countACGT[0];
else if (c == 'C') ++countACGT[1];
else if (c == 'G') ++countACGT[2];
else ++countACGT[3];
}
static void remove(char c)
{
if (c == 'A') --countACGT[0];
else if (c == 'C') --countACGT[1];
else if (c == 'G') --countACGT[2];
else --countACGT[3];
}
add()와 remove()를 수행했다면 countACGT 배열은 아래와 같이 된다.
이 때 check() 메서드가 true를 리턴하므로 count가 +1 된다.
다음 슬라이딩 윈도우를 하면 아래와 같이 된다.
이 때 check() 메서드가 true를 리턴하므로 count가 +1 된다.
총 2번 check() 메서드가 true를 리턴했으므로 정답은 2가된다.
'자료구조 & 알고리즘 > BOJ' 카테고리의 다른 글
[java] 백준 17298번 문제(오큰수) (0) | 2025.03.19 |
---|---|
[java] 백준 1874번 문제(스택 수열) (0) | 2025.03.18 |
[Java] 백준 10986번 문제(나머지 합) (0) | 2024.07.06 |
[Java] 백준 11660번 문제(구간 합 구하기 5) (0) | 2024.07.04 |
[Java] 백준 11659번 문제(구간 합 구하기 4) (1) | 2024.07.03 |