1. 문제설명
지우고 싶은 문자열 S와 지울 수 있는 문자열 A1, A2, …, AM이 주어진다. 문자열 Ai 들은 각자 Xi라는 점수를 가진다. 문자열 S를 삭제 연산을 이용하여 모두 제거하려고 한다.
삭제 연산 두 가지
- 문자열 S의 부분 문자열 중에 문자열 Ai 가 존재한다면 해당하는 부분을 지우고, Xi 만큼의 점수를 얻는다. (여러 부분 존재해도 한 번만 지운다.)
- 문자열 S에서 문자 하나를 지우고 점수를 1점을 얻을 수 있다.
삭제 연산을 이용하여 문자열 S를 지우려고 할 때 얻을 수 있는 최대 점수를 구하는 문제이다.
- 시간 제한: 1초
- 메모리 제한: 512MB
2. 접근 방식
- DP 방법을 사용한다.
- 문자열 S의 각 위치에 대해 그 위치까지의 최대 점수를 저장하는 1차원 dp 배열을 사용한다.
- 각 위치에서 고려하는 두 가지 경우
- 해당 위치의 문자를 제거하지 않는 경우
- 해당 위치에서 끝나는 부분 문자열을 제거하는 경우
- 부분 문자열을 제거하는 경우, 모든 가능한 부분 문자열에 대해 점수를 계산하고 최대값을 선택한다.
- 점수 계산
- 단순히 문자 하나를 제거할 때는 1점
- 주어진 문자열을 제거할 때는 해당 문자열의 점수
- HashMap을 사용해서 문자열을 검사한다. (키는 문자열, 값은 해당 문자열의 점수)
- dp[S.length()] 가 최종 결과가 된다.
3. 최종 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s = br.readLine(); // 문자열 S
int m = Integer.parseInt(br.readLine()); // 지울 수 있는 문자열 개수
Map<String, Integer> substrings = new HashMap<>(); // 지울 수 없는 문자열을 저장
StringTokenizer st;
for(int i=0; i<m; i++) {
st = new StringTokenizer(br.readLine());
String substring = st.nextToken();
int score = Integer.parseInt(st.nextToken());
substrings.put(substring, score);
}
int[] dp = new int[s.length()+1];
for(int i=1; i<=s.length(); i++) {
dp[i] = dp[i-1] + 1; // 한 글자 제거하는 경우
for(String substr : substrings.keySet()) { // 해당 위치에서 끝나는 부분 문자열을 제거하는 경우
if(i >= substr.length() && s.substring(i - substr.length(), i).equals(substr)) {
dp[i] = Math.max(dp[i], dp[i - substr.length()] + substrings.get(substr));
}
}
}
System.out.println(dp[s.length()]);
}
}
반응형
'알고리즘 문제 > 백준' 카테고리의 다른 글
[백준] 7579번: 앱 (Java) (2) | 2024.10.01 |
---|---|
[백준] 2138번: 전구와 스위치 (Java) (0) | 2024.10.01 |
[백준] 11048번: 이동하기 (Java) (0) | 2024.09.24 |
[백준] 17779번: 게리맨더링 2 (Java) (2) | 2024.09.20 |
[백준] 17140번: 이차원 배열과 연산 (Java) (1) | 2024.09.19 |
댓글