자료구조 공부/String

백준 1786 (찾기)

kdhoooon 2021. 3. 23. 16:57

www.acmicpc.net/problem/1786

 

1786번: 찾기

첫째 줄에, T 중간에 P가 몇 번 나타나는지를 나타내는 음이 아닌 정수를 출력한다. 둘째 줄에는 P가 나타나는 위치를 차례대로 공백으로 구분해 출력한다. 예컨대, T의 i~i+m-1번 문자와 P의 1~m

www.acmicpc.net

 

문제가 길어서 링크를 넣는다.

이 문제에서 풀이 방식을 설명하고 있다.

풀이는 KMP 알고리즘을 이용하면 된다.

 

KMP 알고리즘은 빠르게 같은 문자를 찾는 방식이다.

 

접두사로 접미사에 얼마나 연속적으로 나오는가를 이용하는 알고리즘이다 시간복잡도가 O(n) 에 가깝기 때문에 많이 사용 되고 있다.

 

bowbowbow.tistory.com/6

 

KMP : 문자열 검색 알고리즘

문자열 검색이 뭐지? 워드프로세서를 사용할 때 찾기 기능을 사용한적 있을 겁니다. 브라우저에서도 Ctrl+F 단축키를 눌러 검색할 수 있습니다. 아래 이미지는 브라우저에서 "테이프"를 검색했

bowbowbow.tistory.com

 

자세한 구동방식은 이블로그에 정말 잘 정리되어 있다.

 

KMP 알고리즘 코드의 핵심은

while(j > 0 && T.charAt(i) != P.charAt(j)) {
	j = table[j - 1];
}

이 부분이다. 

table 배열은 이미 접두사가 접미사에 얼마나 반복이 되는지 저장을 해두었다.

while 문을 통해 겹치지 않는 부분까지 중간과정을 건너 뛰게 된다.

 

KMP 알고리즘의 핵심은 비교문자와 찾고자하는 문자가 어디까지 같은 문자였는지를 이용하는 방식이다.

 

<전체코드>

import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;

import javax.management.Query;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class Main {

	static StringBuilder sb = new StringBuilder();
	
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        
        String T = bufferedReader.readLine();
        String P = bufferedReader.readLine();
        
        int lenT = T.length();
        int lenP = P.length();
        
        int[] table = new int[lenP];
        
        int j = 0;
        for(int i = 1; i < lenP ; i++) {
        	while(j > 0 && P.charAt(i) != P.charAt(j)) {
        		j = table[j - 1];
        	}
        	
        	if(P.charAt(i) == P.charAt(j)) {
        		table[i] = ++j;
        	}
        }
        
        int count = 0;
        
        j = 0;
        
        for(int i = 0 ; i < lenT; i++) {
        	while(j > 0 && T.charAt(i) != P.charAt(j)) {
        		j = table[j - 1];
        	}
        	
        	if(T.charAt(i) == P.charAt(j)) {
        		if(j == lenP - 1) {
        			count++;
        			sb.append((i - j + 1) + " ");
        			j = table[j];
        		}
        		else {
        			j++;
        		}
        	}
        }
        
        System.out.println(count+ "\n" + sb);
    }
        
}

'자료구조 공부 > String' 카테고리의 다른 글

백준 1062 (가르침)  (0) 2021.04.20
정규표현식 정리 - 백준 (1013, 2857, 2671, 2870)해설 포함  (0) 2021.03.23
백준 9935 (문자열 폭발)  (0) 2021.03.19
백준 1958 ( LCS 3)  (0) 2021.03.19
백준 9252 (LCS 2)  (0) 2021.03.18