본문 바로가기

백준 문제 풀이

백준 1786번 - 찾기(C++)

728x90

https://www.acmicpc.net/problem/1786

 

1786번: 찾기

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

www.acmicpc.net

 

KMP 알고리즘의 기본 문제이다. 문제에서도 친절하게 KMP알고리즘에 대해 설명하고 있다.

 

https://tigerfrom2.tistory.com/400

 

문자열 찾기 - KMP 알고리즘

KMP 알고리즘이란? KMP 알고리즘이란 문자열에서 단어를 빠르게 골라낼 수 있는 알고리즘이다. 러프하게 생각하면 쉽게 문자를 찾아낼 수 있지만 이것은 아주 느리다. KMP의 아이디어 KMP의 중요한

tigerfrom2.tistory.com

 

위 포스팅에 KMP알고리즘에 대해 설명해놓았으니 참고하면 좋다. 

이 문제는 getline 만 조심하면 KMP알고리즘을 그대로 사용할 수 있다.

#include <iostream>
#include <vector>
#include <string>
using namespace std;

int cnt = 0;
vector<int> idx;

vector<int> createTable(string target) {
	int N = target.size();
	vector<int> table(N, 0);
	int j = 0;
	for (int i = 1; i < N; i++) {
		while (j > 0 && target[i] != target[j]) {
			j = table[j - 1];
		}

		if (target[i] == target[j]) {
			table[i] = ++j;
		}
	}

	return table;
}

void KMP(string input, string target, vector<int>& table) {
	int j = 0;
	for (int i = 0; i < input.size(); i++) {
		while (j > 0 && input[i] != target[j]) {
			j = table[j - 1];
		}

		if (input[i] == target[j]) {
			if (j == target.size() - 1) {
				cnt++;
				idx.push_back(i - target.size() + 2);

				j = table[j];
			}
			else {
				j++;
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	string input;	
	string target;

	getline(cin, input);
	getline(cin, target);

	vector<int> table = createTable(target);
	KMP(input, target, table);
	
	cout << cnt << '\n';

	for (int id : idx) cout << id << ' ';
}