문제 풀이 날짜: 2023.08.03
포스트 작성일: 2023.08.03
* 학습 목적으로 작성하는 글입니다. 풀이가 정석적이지 못할 수도 있습니다.
문제 출처
백준 온라인 저지 12891번: DNA 비밀번호 (실버2)
키워드
문자열, 슬라이딩 윈도우
풀이 접근법
- 연속된 부분 문자열을 찾아야 하기 때문에 부분 집합이나 백트랙킹을 풀 수 없다.
- 또, 입력의 크기가 1,000,000이므로 투 포인터로 모든 구간을 구하려고 하면 시간초과가 난다.
- 따라서 투 포인터의 일종이면서도 left와 right의 간격이 항상 일정한 슬라이딩 윈도우 기법으로 답을 구한다.
- 구간을 한 칸씩 옮기면서, left가 가리키는 문자는 결과에서 제하고, right가 가리키는 문자를 결과에 추가하면서 탐색한다.
- 각 부분 문자열이 포함하는 문자의 수가 문제에서 제시한 문자의 수보다 크거나 같다면 조건을 충족한다. 결과의 수를 1 증가시킨다.
코드
import java.io.*;
import java.util.*;
public class Main {
private static int count = 0;
private static Map<Character, Integer> map = new HashMap<>();
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] temp = br.readLine().split(" ");
map.put('A', 0);
map.put('C', 1);
map.put('G', 2);
map.put('T', 3);
int S = Integer.parseInt(temp[0]);
int P = Integer.parseInt(temp[1]);
int[] answer = new int[4];
int[] result = new int[4];
String word = br.readLine();
temp = br.readLine().split(" ");
for(int i = 0; i < 4; i++) {
answer[i] = Integer.parseInt(temp[i]);
}
for(int i = 0; i < P; i++) { //첫 구간 초기화
char curr = word.charAt(i);
result[map.get(curr)]++;
}
if(isSameArr(result, answer)) {
count++;
}
int left = -1;
char prev = ' ';
char curr = ' ';
for(int right = P; right < S; right++) { //현재 부분문자열의 끝을 가리킴
left = right - P; //이전 부분문자열의 시작점
curr = word.charAt(right);
prev = word.charAt(left);
result[map.get(prev)]--;
result[map.get(curr)]++;
if(isSameArr(result, answer)) {
count++;
}
}
System.out.println(count);
}
private static boolean isSameArr(int[] result, int[] answer) {
for(int i = 0; i < result.length; i++) {
if(result[i] < answer[i]) {
return false;
}
}
return true;
}
}
슬라이딩 윈도우를 처음 사용해본 문제이다. 말만 들어서는 어려울 것 같지만 투 포인터의 응용 버전에 불과하다. 문자열 탐색에 응용하면 좋을 듯하니 잘 기억해두는 것이 좋겠다.
참고한 링크
https://7357.tistory.com/240
git 링크
(git 링크 첨부)
'Study > Problem Solving' 카테고리의 다른 글
[백준 / Java] 2493번: 탑 (골드5) (0) | 2023.08.07 |
---|---|
[백준 / Java] 2023번: 신기한 소수 (골드5) (0) | 2023.08.03 |
[백준 / Java] 2961번: 도영이가 만든 맛있는 음식 (실버2) (0) | 2023.08.03 |
[백준 / Java] 2839번: 설탕 배달 (실버4) (0) | 2023.08.02 |
[백준 / Java] 1244번: 스위치 켜고 끄기 (실버4) (0) | 2023.08.01 |