9935 문자열 폭발
9935 문자열 폭발 (c++)
문제
https://www.acmicpc.net/problem/9935
접근 방식
스택, 문자열
1차시도
- str.find()를 이용해서 지워야할 target의 시작위치를 찾고, 지우기를 반복 (시간초과)
2차시도
- 직접 find 함수를 만들어서 erase 대신 str을 target의 전 문자열과 후 문자열의 합으로 갱신 (시간초과)
3차시도
- 못풀겠어서 알고리즘 분류를 봄, 스택이 적혀있었음
- 생각해보니 trigger를 target의 끝문자로 잡고 trigger가 발견될때마다 스택에서 꺼내서 체크하면 될 것 같았음
- 일단 trigger를 target의 마지막 char로 설정
- 문자열을 순회하다 trigger을 발견하면 아래의 과정을 실행
- target의 길이와 현재 stack의 길이를 비교한다.
- stack의 길이가 더 짧으면 target이 아니므로 cotinue;
- stack의 길이가 target의 길이보다 길거나 같으면 아래의 과정을 진행
- target의 길이만큼 stack에서 꺼낸다.
- stack은 LIFO이므로 reverse를 해준다.
- 꺼낸 문자열과 target이 같으면 그대로 진행
- 다르면 다시 stack에 집어넣어 주기
- target의 길이와 현재 stack의 길이를 비교한다.
문제 풀이
#pragma GCC optimize("Ofast")
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
string str, target;
stack<char> stk;
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> str >> target;
int strLength = str.length();
int targetLength = target.length();
for (int i = 0; i < strLength; ++i)
{
if (str[i] == target[targetLength - 1])
{
if (stk.size() >= targetLength - 1)
{
// 검사
string temp = "";
for (int j = 0; j < targetLength - 1; ++j)
{
temp += stk.top(); stk.pop();
}
reverse(temp.begin(), temp.end());
temp += str[i];
if (temp == target)
{
continue;
}
else
{
for (int j = 0; j < targetLength - 1; ++j)
{
stk.push(temp[j]);
}
}
}
}
stk.push(str[i]);
}
string answer = "";
while (!stk.empty())
{
answer += stk.top(); stk.pop();
}
if (answer.length() == 0) cout << "FRULA\n";
else
{
reverse(answer.begin(), answer.end());
cout << answer << '\n';
}
return 0;
}
다시 생각해 볼 점
- ‘문자열이 안풀리면 세로로 세워보자’ 라는걸 항상 기억하자.