2021. 6. 27. 20:23ㆍ알고리즘 관련/Stack
1. 괄호 쌍이나 문자 확인 유형 (기본 유형)
2. 오큰수 유형 (심화 유형)
3. 커서 이동 유형
4. 후위 표현식 유형
1. 기본 유형 : 괄호 쌍이나 문자 확인 유형
괄호 (실버 4) : https://www.acmicpc.net/problem/9012
좋은 단어 (실버 4): https://www.acmicpc.net/problem/3986
문자열 폭발 (골드 4) : https://www.acmicpc.net/problem/9935
=> 괄호 혹은 문자의 순서, 규칙이 조건을 만족하는지 확인하는 유형.
=> 보통은 input을 스택안에 넣어두고, 들어오는 input에 따라 규칙이 맞으면 true 혹은 pop, 규칙이 틀리면 false 혹은 전부 pop.
=> 괄호쌍 : 스택을 하나 생성하고, input이 "(" 일 시 스택에 넣는다. input이 ")"일 시 스택에서 "("를 하나 pop한다. 만일 "("이 없는데 input이 ")"일 경우, 또는 마지막에 스택에 "("이 남았을 경우 false를 리턴.
괄호 문제의 예시 코드.
#include <stdio.h>
#include <iostream>
#include <stack>
using namespace std;
void isVPS()
{
stack<char> s, input;
char c, top;
while ((c = getchar()) != '\n')
input.push(c);
while (!input.empty())
{
top = input.top();
input.pop();
if (top == ')')
s.push(top);
else
{
if (s.empty())
{
cout << "NO" << '\n';
return;
}
s.pop();
}
}
if (!s.empty())
{
cout << "NO" << '\n';
return;
}
cout << "YES" << '\n';
return;
};
int main(void)
{
int N;
char c;
scanf("%d", &N);
cin.ignore();
while (N-- > 0)
{
isVPS();
}
return 0;
}
2. 오큰수 유형 (심화 유형)
오큰수 (골드 4) : https://www.acmicpc.net/problem/17298
오등큰수 (골드 3) : https://www.acmicpc.net/problem/17299
탑 (골드 5) : https://www.acmicpc.net/problem/2493
오큰수 : https://sanghoonly.tistory.com/17
=> 현재 들어오는 값과 스택의 top을 비교하여, 값을 넣거나 빼는 유형.
=> 오큰수의 인덱스를 넣는 스택 하나와, 오큰수를 담는 결과 배열을 하나 생성.
=> 수열을 순회하면서, 들어온 수보다 스택 맨 위의 값이 크면 stack에다 push.
=> 작을 경우, while문 돌면서 스택 맨 위의 값이 현재 값보다 커질때까지 pop, stack에서 나온 인덱스를 바탕으로 결과 배열 값 갱신.
=> 수열 순회 종료 후, 스택에 남아있는 수를 pop 하면서, 인덱스에 해당하는 결과 배열 값을 -1로 수정.
예시 코드 (탑)
#include <iostream>
#include <stack>
#include <stdio.h>
using namespace std;
int main(void)
{
int N, m;
scanf("%d", &N);
cin.ignore();
int towers[N], received[N];
stack<int> s;
for (int i = 0; N > i; i++)
{
scanf("%d", &m);
towers[i] = m;
}
for (int i = 0; N > i; i++)
{
if (s.empty())
{
s.push(i);
received[i] = i;
}
else if (towers[s.top()] < towers[i])
{
while (!s.empty() && (towers[s.top()] < towers[i]))
s.pop();
received[i] = !s.empty() ? s.top() : i;
s.push(i);
}
else
{
received[i] = s.top();
s.push(i);
}
}
for (int i = 0; N > i; i++)
{
if (received[i] == i)
received[i] = 0;
else
received[i]++;
}
for (int i = 0; N > i; i++)
cout << received[i] << ' ';
return 0;
}
3. 커서 이동 유형
에디터 (실버 3) : https://www.acmicpc.net/problem/1406
키로거 (실버 3) : https://www.acmicpc.net/problem/5397
=> 커서가 존재하여, 오른쪽 또는 왼쪽으로 이동하며 추가 & 삭제하는 경우
=> 커서의 왼쪽 단어를 담는 left stack, 오른쪽을 담는 right stack의 두 개 스택이 필요.
=> 커서 왼쪽으로 이동시 -> left stack에는 right stack의 맨 위 요소를 push, 반대로 right에서는 pop.
=> 커서 오른쪽 이동시 -> 왼쪽 이동의 반대로 동작.
=> 글자 삭제시 -> left에서 pop.
=> 글자 추가시 -> left에 push.
예시 코드(에디터)
#include <iostream>
#include <stack>
#include <deque>
using namespace std;
int main(void)
{
int N;
char cmd, addChar;
deque<char> left;
deque<char> right;
string str;
getline(cin, str);
cin >> N;
for (int i = 0; str.size() > i; i++)
left.push_back(str[i]);
while (N-- > 0)
{
cin >> cmd;
if (cmd == 'L')
{
if (left.empty())
continue;
right.push_back(left.back());
left.pop_back();
}
if (cmd == 'D')
{
if (right.empty())
continue;
left.push_back(right.back());
right.pop_back();
}
if (cmd == 'B')
{
if (left.empty())
continue;
left.pop_back();
}
if (cmd == 'P')
{
cin >> addChar;
left.push_back(addChar);
}
}
for (int i = 0; left.size() > i; i++)
cout << left[i];
for (int i = right.size() - 1; i >= 0; i--)
cout << right[i];
return 0;
}
4. 후위 표현식 유형
후위 표현식 2 (실버 3) : https://www.acmicpc.net/problem/1935
후위 표현식 (골드 4) : https://www.acmicpc.net/problem/1918
=> 중위 표현식을 후위 표기식으로 바꾸거나, 그 반대로 바꿈.
=> 혹은 답을 계산하라는 문제.
=> 스택을 이용하여, 숫자 혹은 문자를 담으면 됨.
=> 문자를 담는 경우, 연산 우선순위는 () > * or / > + or -
=> 스택 맨위 연산자보다 우선 순위가 같거나 낮은 연산자가 들어올 경우 -> 우선순위가 같다면 스택 맨 위에꺼 꺼내고 자기가 들어가기, 우선순위가 낮다면 같거나 높아질 때까지 pop
=> 스택 맨위 연산자보다 우선 순위가 높은 연산자가 들어올 경우 -> push.
=> 괄호의 경우: "(" : push. ")" : "(" 마주칠 때 까지 계속 stack을 pop.
예제 코드(후위 표현식)
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main()
{
string str;
stack<char> oper;
cin >> str;
for (int i = 0; i < str.length(); i++)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
cout << str[i];
}
else
{
if (str[i] == '(')
oper.push(str[i]);
else if (str[i] == '*' || str[i] == '/')
{
while (!oper.empty() && (oper.top() == '*' || oper.top() == '/'))
{
cout << oper.top();
oper.pop();
}
oper.push(str[i]);
}
else if (str[i] == '+' || str[i] == '-')
{
while (!oper.empty() && oper.top() != '(')
{
cout << oper.top();
oper.pop();
}
oper.push(str[i]);
}
else if (str[i] == ')')
{
while (!oper.empty() && oper.top() != '(')
{
cout << oper.top();
oper.pop();
}
oper.pop();
}
}
}
while (!oper.empty())
{
cout << oper.top();
oper.pop();
}
return 0;
}
'알고리즘 관련 > Stack' 카테고리의 다른 글
17299 - 오등큰수 (0) | 2021.06.21 |
---|---|
17298 - 오큰수 (0) | 2021.06.21 |