티스토리 뷰

blog.naver.com/kks227/220917078260

 

KMP 알고리즘(Knuth–Morris–Pratt Algorithm) (수정: 2019-09-01)

KMPlayer가 아니다 안녕하세요. 한동안 그래프를 줄창 했듯이 이제부터는 문자열을 줄창 하게 될 겁니다...

blog.naver.com

 

$S[1, i]$ 에서 prefix와 suffix가 같은 최대 길이를 fail[i]라 저장한 전처리 배열을 먼저 만든다.

그 후, 위 그림과 같이 불일치가 발생하였을 때마다, fail에 해당하는 값만큼 건너뛰어, i는 절대 감소하지 않고, j만 이동하도록 만들어 주면 시간복잡도가 $O(N+M)$이 보장된다.

 

fail 함수를 구하는 방법은 단순히 위 알고리즘을 S에서 S를 탐색하는 방향으로 바꾸고, 일치가 발생할 때마다 fail함수에 현재 i위치에 대한 j위치를 기록해주면 된다.

 

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int MAXN = 1e6;

string SS, TT;
int N, M;
char S[MAXN+10], T[MAXN+10];

int fail[MAXN+10];

int main()
{
	getline(cin, SS);
	getline(cin, TT);

	N=SS.size(); M=TT.size();
	for(int i=1; i<=N; i++) S[i]=SS[i-1];
	for(int i=1; i<=M; i++) T[i]=TT[i-1];

	for(int i=2, j=1; i<=M;)
	{
		if(T[i]!=T[j] || j>M)
		{
			if(j==1) i++;
			else j=fail[j-1]+1;
		}
		else
		{
			fail[i]=j;
			i++; j++;
		}
	}

	vector<int> ans;
	for(int i=1, j=1; i<=N;)
	{
		if(S[i]!=T[j] || j>M)
		{
			if(j==1) i++;
			else j=fail[j-1]+1;
		}
		else
		{
			i++; j++;
			if(j>M) ans.push_back(i-M);
		}
	}
	printf("%d\n", ans.size());
	for(auto it : ans) printf("%d ", it);
}

'알고리즘 & 자료구조 정리' 카테고리의 다른 글

Andrew's Chain  (0) 2020.11.04
Graham's Scan  (0) 2020.11.04
이중 결합 요소 (Biconnected Component)  (1) 2020.10.07
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함