BOJ

[c/c++] 백준 9935

qefoi 2022. 11. 15. 23:07

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

9935번: 문자열 폭발

첫째 줄에 문자열이 주어진다. 문자열의 길이는 1보다 크거나 같고, 1,000,000보다 작거나 같다. 둘째 줄에 폭발 문자열이 주어진다. 길이는 1보다 크거나 같고, 36보다 작거나 같다. 두 문자열은 모

www.acmicpc.net

접근 방식


처음엔 괄호가 옳바르게 쓰였는지 확인하는 문제처럼 접근했다.
하지만 괄호 문제와는 다르게 폭발 문자열이 괄호처럼 한쌍으로 이루어진게 아니었기 때문에 괄호처럼 푸는 것은 어려울 것이라 생각하고 다른 방법을 생각해보았다.

그 다음으로 생각해본건 stack에 한 글자씩 넣으며 문자열이 있는지 검사하는 방법을 생각했다.
하지만 완전 탐색을 하게 되면 시간 복잡도가 O(n^2)이 되는데 n<=1,000,000이므로 시간 초과가 나게 된다.

풀이 방법

입력을 한 글자씩 받게 되는데 한 글자를 받을 때 stack에서 생길 수 있는 폭발 문자열의 최대 개수는 1개이다.
그리고 입력이 폭발 문자열의 마지막 문자여야만 폭발 문자열이 생기게 된다.
즉 입력을 받은 곳이 아닌 엉뚱한 곳에서 폭발 문자열이 생기지 않는다는 말이다.
그래서 한 글자를 받았을 때 stack의 크기가 폭발 문자열의 크기보다 크다면 top에서 폭발 문자열의 크기만큼만 빼준 index부터만 검사하여 폭발 문자열이라면 그 크기만큼 pop해주면 폭발 문자열을 제거할 수 있다.
이렇게 하면 시간 복잡도가 O(nm)이 되는데 n<=1,000,000 m<=36이므로 시간 내에 돌아간다.

코드

#include<iostream>
#include<string>

using namespace std;

int main()
{
    string s,target;
    char sta[1000001];
    int top=0;
    cin>>s>>target;
    
    int s_len=s.length();
    int t_len=target.length();
    
    for(int i=0;i<s_len;i++){
        sta[top++]=s[i];
        if(top>=t_len){
            int flag=1;
            for(int j=0;j<t_len;j++){
                if(sta[j+top-t_len]!=target[j]) flag=0;
            }
            if(flag) top-=t_len;
        }
    }
    
    sta[top]='\0';
    
    if(!top) cout<<"FRULA";
    else cout<<sta;
    
    return 0;
}

배열이 아닌 vector로 구현하려고 했지만 vector로 하게 되면 문자열 길이만큼 pop해주어야해서 그냥 배열로 구현하여 top을 이용하여 index만 바꿔주는 식으로 구현했다. 하지만 이렇게 하면 stack에 top보다 큰 index에도 값이 존재할 수 있으므로 마지막에 '\0'을 넣어주어 문자열의 끝을 구분해주었다.