PS

[BOJ] 5525번: IOIOI

yunny_world 2022. 6. 15. 18:31

https://www.acmicpc.net/problem/5525

 

5525번: IOIOI

N+1개의 I와 N개의 O로 이루어져 있으면, I와 O이 교대로 나오는 문자열을 PN이라고 한다. P1 IOI P2 IOIOI P3 IOIOIOI PN IOIOI...OI (O가 N개) I와 O로만 이루어진 문자열 S와 정수 N이 주어졌을 때, S안에 PN이 몇

www.acmicpc.net


접근 방법

일단 주어진 문자열 S에서 IOI 를 세려고 했다. IOI인 O의 인덱스를 chk배열에 저장한 후,

chk배열을 순회하면서 chk[j]-chk[j-1]==2 으로 chk배열의 인접한 두 값의 차이가 2이면 IOI가 이어지는 것으로 판단하였다.


풀이 / 시간 복잡도

처음에는 chk배열의 모든 인덱스를 대상으로 이어지는 IOI의 O 개수(k)를 1로 설정해 놓고 n에 도달하면 답(ans)에 1씩 추가하는 방식으로 구현했었다. 이렇게 하면 대략 \( O(m^2) \)으로 TLE 가 나온다.

그래서 chk배열을 순회할 때 이어지는 최장 IOI의 O의 개수(k)를 찾고,

다음에 순회할 chk배열 인덱스를 직전 최장 IOI의 인덱스 다음으로 두어서 대략 \( O(m) \)으로 TLE를 해결했다.

이때, 답(ans)에는 ans+=max(k-n+1, 0) 으로 각 이어지는 최장 IOI 마다 더해주면 된다.


코드

#include <bits/stdc++.h>
#define ll long long int
#define pll pair<ll, ll>
#define pii pair<int, int>
#define X first
#define Y second
using namespace std;
int dx[]={-1, 1, 0, 0};
int dy[]={0, 0, -1, 1};
vector<int> chk;
void solve ()
{
    int n, m; cin>>n>>m;
    string s; cin>>s;
    for(int i=1;i<m-1;i++)
        if(s[i]=='O' && s[i-1]=='I' && s[i+1]=='I') chk.push_back(i);
    int ans=0;
    for(int i=0;i<chk.size();)
    {
        int k=1;
        for(int j=++i;j<chk.size();j++) 
        {
            i=j;
            if(chk[j]-chk[j-1]==2) k++;
            else break;
        }
        ans+=max(k-n+1, 0);
    }
    cout<<ans<<'\n';
}
int main()
{
    ios::sync_with_stdio(0); cin.tie(0);
    int tc=1;
    while(tc--) solve();
    return 0;
}

처음에 TLE 받았을 때, KMP 알고리즘의 존재에 대해 알게 되었는데, 나중에 공부할 기회가 올 지 모르겠다.. 지금은 귀찮다.. 방학 때 해야지...

일단 나는 그냥 구현으로 푼 것 같다.

'PS' 카테고리의 다른 글

PS 환경 설정 글 모음  (0) 2022.07.23
[BOJ] 2785번: 체인  (0) 2022.06.23
[BOJ] 1966: 프린터 큐  (0) 2022.06.12
[BOJ] 2981: 검문  (1) 2022.06.08
[BOJ] 1561번: 놀이공원  (0) 2022.06.07