문제 : https://www.acmicpc.net/problem/11585


문자열 KMP

 우리는 주어지는 입력 A, B에서 B를 원형으로 회전시켜가며 A가 있는지 없는지 탐색할 수 있어야된다.

따라서, 문자열 검색인 KMP 알고리즘을 생각해야되고 B를 원형으로 회전시켜가며 생각하는 부분은 B 에다가 B를 한 번 더 붙여주면 쉽게 해결이 된다.

 

예시) 

I W A N T M E A T 

E A T I W A N T M 를

E A T I W A N T M E A T I W A N T M 에서 I W A N T M E A T 을 찾는 문제로 바꿔서 바라보면 쉽게 해결할 수 있다.

#include<iostream>
#include<vector>

using namespace std;

int N;
char input1[1000001], input2[2000001];

vector<int> getPartialMatch() {
	vector<int> pi(N, 0);
	int begin = 1, matched = 0;
	while (begin + matched < N) {
		if (input1[begin + matched] == input1[matched]) {
			matched++;
			pi[begin + matched - 1] = matched;
		}
		else {
			if (matched == 0) begin++;
			else {
				begin += matched - pi[matched - 1];
				matched = pi[matched - 1];
			}
		}
	}
	return pi;
}

int KMP() {
	int cnt = 0;
	vector<int> pi = getPartialMatch();
	int begin = 0, matched = 0;
	while (begin < N) {
		if (matched < N && input2[begin + matched] == input1[matched]) {
			matched++;
			if (matched == N) cnt++;
		}
		else {
			if (matched == 0) begin++;
			else {
				begin += matched - pi[matched - 1];
				matched = pi[matched - 1];
			}
		}
	}
	return cnt;
}
int gcd(int A, int B) {
	while (B) {
		int r = A % B;
		A = B;
		B = r;
	}
	return A;
}
int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	cin >> N;
	for (int i = 0; i < N; i++)
		cin >> input1[i];
	for (int i = 0; i < N; i++)
		cin >> input2[i];
	for (int i = N; i < 2 * N; i++)
		input2[i] = input2[i - N];
	int cnt = KMP();
	int r = gcd(N, cnt);
	cout << cnt / r << '/' << N / r << '\n';
	return 0;
}

 

'Problem Solving > BOJ' 카테고리의 다른 글

[BOJ] 11559 : Puyo Puyo  (0) 2020.05.21
[BOJ] 1038 : 감소하는 수  (0) 2020.05.20
[BOJ] 2671 : 잠수함 식별  (0) 2020.05.15
[BOJ] 1305 : 광고  (0) 2020.05.08
[BOJ] 4354 : Power Strings  (0) 2020.05.08

+ Recent posts