https://www.acmicpc.net/problem/9177
코드설명
먼저 이 문제는 깊이우선탐색으로 풀 수 있습니다.
각 단어의 인덱스를 관리하면서 C가 마지막 길이까지 가면 성공한 것입니다.
처음에는 시간복잡도 고려하지 않고 접근했고, 시간초과가 발생했습니다.
시간복잡도는 최악의 경우 400^2 입니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int N;
static String A, B, C;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
for(int i=0; i<N; i++){
st = new StringTokenizer(br.readLine());
A = st.nextToken();
B = st.nextToken();
C = st.nextToken();
System.out.println("Data set "+ (i+1)+": "+ ( solve(0, 0, 0) ? "yes" : "no") );
}
}
static boolean solve(int a_idx, int b_idx, int c_idx){
if(c_idx == C.length()) {
return true;
}
boolean ret = false;
if(a_idx < A.length() && C.charAt(c_idx) == A.charAt(a_idx) ) {
ret |= solve(a_idx + 1, b_idx, c_idx + 1);
}
if(b_idx < B.length() && C.charAt(c_idx) == B.charAt(b_idx)) {
ret |= solve(a_idx, b_idx + 1, c_idx + 1);
}
return ret;
}
}
이에 대해 동적계획법으로 대처했습니다.
package Main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int N;
static String A, B, C;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
for(int i=0; i<N; i++){
st = new StringTokenizer(br.readLine());
A = st.nextToken();
B = st.nextToken();
C = st.nextToken();
for(int j=0; j<205; j++) {
for(int k=0; k<205; k++) {
Arrays.fill(dp[j][k], -1);
}
}
System.out.println("Data set "+ (i+1)+": "+ ( solve(0, 0, 0) ? "yes" : "no") );
}
}
static int[][][] dp = new int[205][205][410];
static boolean solve(int a_idx, int b_idx, int c_idx){
if(dp[a_idx][b_idx][c_idx] == 1) return true;
else if(dp[a_idx][b_idx][c_idx] == 0) return false;
if(c_idx == C.length()) {
return true;
}
boolean ret = false;
if(a_idx < A.length() && C.charAt(c_idx) == A.charAt(a_idx) ) {
ret |= solve(a_idx + 1, b_idx, c_idx + 1);
}
if(b_idx < B.length() && C.charAt(c_idx) == B.charAt(b_idx)) {
ret |= solve(a_idx, b_idx + 1, c_idx + 1);
}
dp[a_idx][b_idx][c_idx] = ret ? 1 : 0;
return ret;
}
}
하지만, 좀 더 최적화시키면, 애초에 c_idx가 필요하지 않는걸 알 수 있습니다.
코드
c_idx는 a_idx + b_idx로 찾아냅니다.
좀 찜찜한점은, 목표 String이 전역적으로 선언되어있어 solve 함수내에서 참조되고 있기에 dp[A String][B String]으로만 충분한지 고민되지만, A, B, C의 변수값이 가변적이지 않기에 상관없습니다.
package Main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int N;
static String A, B, C;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
for(int i=0; i<N; i++){
st = new StringTokenizer(br.readLine());
A = st.nextToken();
B = st.nextToken();
C = st.nextToken();
for(int j=0; j<205; j++) {
Arrays.fill(dp[j], -1);
}
System.out.println("Data set "+ (i+1)+": "+ ( solve(0, 0) ? "yes" : "no") );
}
}
static int[][] dp = new int[205][205];
// 현재 A의 앞 a_idx 글자, B의 앞 b_idx의 글자를 이미 사용했을떄 C의 앞글자를 만들 수 있는지를 반환하는 함수
static boolean solve(int a_idx, int b_idx){
if(dp[a_idx][b_idx] == 1) return true;
else if(dp[a_idx][b_idx] == 0) return false;
if((a_idx + b_idx) == C.length()) {
return true;
}
boolean ret = false;
if(a_idx < A.length() && C.charAt(a_idx + b_idx) == A.charAt(a_idx) ) {
ret |= solve(a_idx + 1, b_idx);
}
if(b_idx < B.length() && C.charAt(a_idx + b_idx) == B.charAt(b_idx)) {
ret |= solve(a_idx, b_idx + 1);
}
dp[a_idx][b_idx] = ret ? 1 : 0;
return ret;
}
}
'알고리즘 > 백준' 카테고리의 다른 글
| [백준] 32403 전구 주기 맞추기 - 구현(Implementation) JAVA (0) | 2024.10.23 |
|---|---|
| [백준] 11899 괄호 끼워넣기 - 스택(Stack) JAVA (0) | 2024.10.09 |
| [백준] 3568 iSharp - 문자열(String) + 파싱(Parsing) JAVA (0) | 2024.10.08 |
| [백준] 2852 NBA 농구 - 문자열(String) + 정렬(Sort) JAVA (0) | 2024.10.08 |
| [백준] 3187 양치기 꿍 - BFS(넓이우선탐색) JAVA (0) | 2024.10.04 |