티스토리 뷰

알고리즘/백준

백준 / 1786 찾기 C++

4567은 소수 2021. 3. 1. 23:33

www.acmicpc.net/problem/1786

 

1786번: 찾기

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

www.acmicpc.net

문제에서 kmp 알고리즘을 설명하고 있습니다. kmp 알고리즘을 대략적으로 알고있었지만, 정확하게 다시 알아보기 위해 다음 글을 참고하였습니다.

bowbowbow.tistory.com/6

 

KMP : 문자열 검색 알고리즘

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

bowbowbow.tistory.com

설명을 깔끔하게 잘 해주셨습니다.

 

코드는 다음과 같습니다.

 

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>

using namespace std;

string T, P;
vector<int>pi; // 전처리용
vector<int>result; // 정답 인덱스 저장

void make_text()
{
	getline(cin, T);
	getline(cin, P);
}

// pi배열 얻기
void get_pi(string p)
{
	int m = p.size();
	int j = 0;

	pi.resize(m, 0);

	// 한자리 글은 prefix = suffix라 하지 않으므로 i=1부터
	for (int i = 1; i < m; i++) {
		while ((j > 0) && (p[i] != p[j])) {
			j = pi[j - 1];
		}
		if (p[i] == p[j]) {
			j++;
			pi[i] = j;
		}
	}
}

// kmp 알고리즘
void kmp(string t, string p)
{
	int n = t.size();
	int m = p.size();
	int j = 0;

	for (int i = 0; i < n; i++) {
		while ((j > 0) && (t[i] != p[j])) {
			j = pi[j - 1];
		}
		if (t[i] == p[j]) {
			if (j == (m - 1)) {
				result.push_back(i - m + 1);
				j = pi[j];
			}
			else {
				j++;
			}
		}
	}
}

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

	make_text();
	get_pi(P);
	kmp(T, P);

	cout << result.size() << '\n';

	// 문제에서 인덱스 1부터 시작, kmp는 0부터 시작
	for (int i = 0; i < result.size(); i++)
		cout << result[i] + 1 << '\n';
}

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함