PS

BOJ 11585 - 속타는 저녁 메뉴

728x90

www.acmicpc.net/problem/11585

 

11585번: 속타는 저녁 메뉴

수원이와 친구들은 저녁 메뉴를 잘 선택하지 못한다. 배가 고픈 수원이가 보다 못해 메뉴를 정하곤 하는데 이마저도 반대에 부딪히는 경우에는 수원이가 원형 룰렛을 돌려 결정하곤 한다. 이 원

www.acmicpc.net

 

KMP 를 써서 풀어야 하는 문제이다

원형 룰렛을 구현하는 대신, 문자열을 두배로 늘리고 

이에 패턴 문자열을 맞춰서 KMP 를 써야 한다.

 

- c++

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
 
using namespace std;
 
int N;
string parent, pattern;
char ch;
int cnt;
 
vector<int> make_pi() {
    int pattern_size = pattern.length();
    vector<int> pi(pattern_size, 0);
    int prefix_index = 0;
    for (int suffix_index = 1; suffix_index < pattern_size; suffix_index++) {
        while (prefix_index > 0 && pattern[suffix_index] != pattern[prefix_index]) {
            prefix_index = pi[prefix_index - 1];
        }
        if (pattern[prefix_index] == pattern[suffix_index]) {
            pi[suffix_index] = ++prefix_index;
        }
    }
    return pi;
}
 
void KMP() {
    int pattern_size = pattern.length();
    int parent_size = parent.length();
    vector<int> pi = make_pi();
    int pattern_index = 0;
    for (int parent_index = 0; parent_index < parent_size; parent_index++) {
        while (pattern_index > 0 && parent[parent_index] != pattern[pattern_index]) {
            pattern_index = pi[pattern_index - 1];
        }
        if (parent[parent_index] == pattern[pattern_index]) {
            if (pattern_index == pattern_size - 1) {
                pattern_index = pi[pattern_index];
                cnt++;
            } else {
                pattern_index++;
            }
        }
    }
}
 
void init() {
    cin.tie(0);
    ios_base::sync_with_stdio(0);
 
    cin >> N;
 
    for (int i = 0; i < N; i++) {
        cin >> ch;
        pattern.append(1, ch);
    }
 
    for (int i = 0; i < N; i++) {
        cin >> ch;
        parent.append(1, ch);
    }
    parent.append(parent);
    parent.pop_back();
    // pop_back() 을 해서 맨 뒷 글자를 제거한 이유
    // 원형 판을 구현하지 않고 편의상 코드를 작성하기 위해서
    // parent 의 크기를 두배로 늘렸을 뿐 실제로는 2배 늘린게 아니기 때문.
    // 예를 들어, 두배 늘렸을 때
    // I W A N T M 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 E A T
    // 처럼 2번 카운팅 되기 때문에, 오류로 처리될 수 있다.
    // 실제로는 단 한번만 일치함.
}
 
int gcd(int a, int b) {
    if (a < b)
        swap(a, b);
 
    while (b != 0) {
        int temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}
 
int main() {
    init();
    KMP();
    int num = gcd(cnt, N);
    cout << cnt / num << "/" << N / num;
    return 0;
}
cs

 

 

 

 

처음엔 한 50% 언저리 가서

계속 틀렸습니다가 나왔는데,

알고보니 pop_back() 을 해서 맨 뒷문자를 제거해 줘야 했었다.

 

 

728x90

'PS' 카테고리의 다른 글

BOJ 1913 - 달팽이  (0) 2020.09.17
BOJ 1504 - 특정한 최단 경로  (0) 2020.09.17
BOJ 7569 - 토마토  (0) 2020.09.06
BOJ 2630 - 색종이 만들기  (0) 2020.09.05
BOJ 11724 - 연결 요소의 갯수  (0) 2020.09.04