문제 링크: https://www.acmicpc.net/problem/16916

 

16916번: 부분 문자열

첫째 줄에 문자열 S, 둘째 줄에 문자열 P가 주어진다. 두 문자열은 빈 문자열이 아니며, 길이는 100만을 넘지 않는다. 또, 알파벳 소문자로만 이루어져 있다.

www.acmicpc.net

 

비교하는 문자열의 길이가 짧다면 반복문을 중첩시켜 구할 수 있겠지만, 두 문자열의 최대 길이가 100만이므로 시간초과가 날 것이다. 따라서 KMP 알고리즘을 사용해야 한다. 

 

해당 알고리즘은 접두사와 접미사를 활용하여 판별한다. 

 

import java.math.BigInteger;
import java.util.*;
import java.io.*;
public class Main {
static int t;
static int [] table;
public static void main(String [] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s = br.readLine();
String p = br.readLine();
table = new int [p.length()];
System.out.println(KMP(s,p));
}
public static int KMP(String s, String p){
makeTable(p);
int sLength=s.length();
int pLength=p.length();
int idx =0;
for(int i=0; i<sLength; i++){
while(idx>0 && s.charAt(i) != p.charAt(idx)){
idx=table[idx-1];
}
if(s.charAt(i)==p.charAt(idx)){
if(idx==pLength-1){
idx=table[idx];
return 1;
}
else{
idx+=1;
}
}
}
return 0;
}
public static void makeTable(String p){
int n = p.length();
int idx=0;
for(int i=1; i<n; i++){
while(idx>0 && p.charAt(i)!=p.charAt(idx)){
idx= table[idx-1];
}
if(p.charAt(i)==p.charAt(idx)){
idx++;
table[i]=idx;
}
}
}
}