티스토리 뷰
1786번: 찾기
첫째 줄에, T 중간에 P가 몇 번 나타나는지를 나타내는 음이 아닌 정수를 출력한다. 둘째 줄에는 P가 나타나는 위치를 차례대로 공백으로 구분해 출력한다. 예컨대, T의 i~i+m-1번 문자와 P의 1~m
www.acmicpc.net
문제에서 kmp 알고리즘을 설명하고 있습니다. kmp 알고리즘을 대략적으로 알고있었지만, 정확하게 다시 알아보기 위해 다음 글을 참고하였습니다.
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';
}
'알고리즘 > 백준' 카테고리의 다른 글
백준 / 2252 줄 세우기 C++ (0) | 2021.03.04 |
---|---|
백준 / 1916 최소비용 구하기 C++ (0) | 2021.03.02 |
백준 / 5014 스타트링크 C++ (0) | 2021.03.01 |
백준 / 1311 할 일 정하기 1 C++ (0) | 2021.02.24 |
백준 / 15681 트리와 쿼리 C++ (0) | 2021.02.24 |
댓글