Problem : https://www.acmicpc.net/problem/1786
1786번: 찾기
첫째 줄에, T 중간에 P가 몇 번 나타나는지를 나타내는 음이 아닌 정수를 출력한다. 둘째 줄에는 P가 나타나는 위치를 차례대로 공백으로 구분해 출력한다. 예컨대, T의 i~i+m-1번 문자와 P의 1~m
www.acmicpc.net
Approach
KMP 알고리즘을 활용한 연습문제이다.
KMP 알고리즘에 대한 내용은 여기서 다루지 않고 다음 링크를 참고하면 좋을 것이다. 설명이 정말 명쾌하다.
KMP : 문자열 검색 알고리즘
문자열 검색이 뭐지? 워드프로세서를 사용할 때 찾기 기능을 사용한적 있을 겁니다. 브라우저에서도 Ctrl+F 단축키를 눌러 검색할 수 있습니다. 아래 이미지는 브라우저에서 "테이프"를 검색했
bowbowbow.tistory.com
문제 자체는 KMP 알고리즘을 단순히 구현하는 문제이다.
따라서 KMP 알고리즘의 내용을 이해하고 공부할 수 있는 좋은 연습문제가 될 것이다.
Code
import java.io.*;
import java.util.ArrayList;
/**
* No.1786: 찾기
* url: https://www.acmicpc.net/problem/1786
* hint: KMP 알고리즘 연습문제
*/
public class BOJ1786 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String text = br.readLine();
String pattern = br.readLine();
ArrayList<Integer> ans = kmp(text, pattern);
bw.write(ans.size() + "\n");
for (int a : ans) {
bw.write((a + 1) + " ");
}
bw.close();
br.close();
}
static int[] getPi(String pattern) {
int pLength = pattern.length();
int[] pi = new int[pLength];
int j = 0;
// i는 접미사를 다룸, j는 접두사를 다룸룸
for (int i = 1; i < pLength; i++) {
while (j > 0 && pattern.charAt(i) != pattern.charAt(j)) {
j = pi[j - 1]; // 건너 뜀(재할당)
}
if (pattern.charAt(i) == pattern.charAt(j)) {
pi[i] = ++j;
}
}
return pi;
}
static ArrayList<Integer> kmp(String text, String pattern) {
ArrayList<Integer> res = new ArrayList<>();
int tLength = text.length();
int pLength = pattern.length();
int[] pi = getPi(pattern);
int j = 0;
for (int i = 0; i < tLength; i++) {
while (j > 0 && text.charAt(i) != pattern.charAt(j)) {
j = pi[j - 1]; // 건너 뜀(재할당)
}
if (text.charAt(i) == pattern.charAt(j)) {
if (j == pLength - 1) { // pattern의 끝까지 같으면 정답에 추가
res.add(i - pLength + 1);
j = pi[j];
} else { // 탐색 인덱스를 증가시킴
j++;
}
}
}
return res;
}
}
'Algorithm > Baekjoon Online Judge' 카테고리의 다른 글
[java] 백준 1305 (광고) Platinum 5 (0) | 2021.02.13 |
---|---|
[java] 백준 4354 (문자열 제곱) Platinum 5 (0) | 2021.02.11 |
[java] 백준 17472 (다리 만들기 2) Gold 3 (0) | 2021.01.30 |
[java] 백준 20040 (사이클 게임) Gold 4 (0) | 2021.01.29 |
[java] 백준 4803 (트리) Gold 4 (0) | 2021.01.28 |