두 개의 시계 사진을 서로 회전시켜 같은 시각을 나타내는지 확인하는 문제를 풀었다. 각 시계는 여러 바늘을 가지고 있고, 각 바늘은 시계 방향으로 특정 각도 위치에 있으며, 두 시계의 바늘 배치가 서로 다를 수 있다. KMP 알고리즘을 활용해 두 시계의 바늘 배치가 일치할 수 있는지를 판별했다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static final int MAX = 360000;
// KMP 알고리즘의 pi 배열을 구하는 메서드
public static int[] getPi(boolean[] pattern) {
int[] pi = new int[pattern.length];
int j = 0;
for (int i = 1; i < pattern.length; i++) {
while (j > 0 && pattern[i] != pattern[j]) {
j = pi[j - 1];
}
if (pattern[i] == pattern[j]) {
pi[i] = ++j;
}
}
return pi;
}
// KMP 알고리즘을 이용한 패턴 매칭
public static boolean kmp(boolean[] text, boolean[] pattern) {
int[] pi = getPi(pattern);
int j = 0;
for (int i = 0; i < text.length; i++) {
while (j > 0 && text[i] != pattern[j]) {
j = pi[j - 1];
}
if (text[i] == pattern[j]) {
if (j == pattern.length - 1) {
return true; // 매칭 성공
} else {
j++;
}
}
}
return false; // 매칭 실패
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine().trim());
// 첫 번째 시계의 각도를 저장할 배열
boolean[] clock1 = new boolean[MAX * 2];
boolean[] clock2 = new boolean[MAX];
// 첫 번째 시계 각도 입력 및 표시
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
int angle = Integer.parseInt(st.nextToken());
clock1[angle] = true;
clock1[MAX + angle] = true; // 시계 방향으로 회전 가능성 추가
}
// 두 번째 시계 각도 입력 및 표시
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
int angle = Integer.parseInt(st.nextToken());
clock2[angle] = true;
}
// KMP 알고리즘을 사용하여 같은 시각인지 확인
System.out.println(kmp(clock1, clock2) ? "possible" : "impossible");
}
}
public static int[] getPi(boolean[] pattern) {
int[] pi = new int[pattern.length];
int j = 0;
for (int i = 1; i < pattern.length; i++) {
while (j > 0 && pattern[i] != pattern[j]) {
j = pi[j - 1];
}
if (pattern[i] == pattern[j]) {
pi[i] = ++j;
}
}
return pi;
}
public static boolean kmp(boolean[] text, boolean[] pattern) {
int[] pi = getPi(pattern);
int j = 0;
for (int i = 0; i < text.length; i++) {
while (j > 0 && text[i] != pattern[j]) {
j = pi[j - 1];
}
if (text[i] == pattern[j]) {
if (j == pattern.length - 1) {
return true; // 매칭 성공
} else {
j++;
}
}
}
return false; // 매칭 실패
}
int n = Integer.parseInt(br.readLine().trim());
boolean[] clock1 = new boolean[MAX * 2];
boolean[] clock2 = new boolean[MAX];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
int angle = Integer.parseInt(st.nextToken());
clock1[angle] = true;
clock1[MAX + angle] = true; // 시계 방향으로 회전 가능성 추가
}
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
int angle = Integer.parseInt(st.nextToken());
clock2[angle] = true;
}
System.out.println(kmp(clock1, clock2) ? "possible" : "impossible");
KMP 알고리즘을 통해 두 시계의 바늘 배치가 일치하는지 효율적으로 확인할 수 있었다. 두 시계를 직접 회전시키며 비교하는 대신, 첫 번째 시계를 두 배 길이로 확장하여 회전하는 효과를 시뮬레이션하고, KMP 알고리즘으로 이를 패턴 매칭으로 처리한 것이 핵심이다.