[C++] 백준 17413 단어 뒤집기 2
2021. 7. 6.
반응형

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

 

17413번: 단어 뒤집기 2

문자열 S가 주어졌을 때, 이 문자열에서 단어만 뒤집으려고 한다. 먼저, 문자열 S는 아래와과 같은 규칙을 지킨다. 알파벳 소문자('a'-'z'), 숫자('0'-'9'), 공백(' '), 특수 문자('<', '>')로만 이루어져

www.acmicpc.net

 

1. 서론

 

진짜 쉬워 보이는데 생각보다 생각해줘야 할 것이 많아서 진짜 오래 걸린 문제... ㅠ.ㅠ

이 문제가 그나마 쉬운 점은 테스트 케이스를 진짜 많이 줬다는 점.

 

2. 문제 풀이

 

문제의 포인트 자체는 간단하다. 문자열이 주어지고 그 문자열을 단어 단위로 뒤집는 것이다.

이때 조건이 있는데 '<>' 이 괄호 안에 있는 문자는 뒤집으면 안 된다는 것이다.

단어의 단위는 ' ' << 공백 문자와, '<>' 괄호 안의 있는 단어 두 가지 형태이다.

 

예시를 가져오자면 

< space >space space space< spa c e>

=>

< space >

space

space

space

< spa c e>

 

이렇게 다섯 개의 단어로 이루어져 있는 것이다.

처음엔 그냥 공백 문자랑 괄호 문자랑 이용해서 대충 자르면 되겠지 생각했다. 근데 생각보다 생각할 것이 많았다.

공백 문자 단위로 자르면 공백 문자가 없는 테스트 케이스도 있고, 괄호 문자가 나올 때마다 잘랐더니 괄호 문자 다음에 공백 문자가 나와서 단어가 잘라지는 게 아니라 그냥 괄호 문자가 잘라졌다.

 

결론을 말하자면 for문으로 어떻게든 하려다가 모든 시도가 다 망하고 결국 while문을 썼다.

while문으로 문자열을 한 바퀴 도는데 '<' 괄호의 앞부분이 나오면 그 안에 다른 while문을 써서 '>' 괄호가 닫힐 때까지 문자열을 저장한다.

그리고 그렇게 완성된 단어를 배열에 넣는다. 그리고 괄호 기호가 나오지 않는 경우에는 공백 문자가 나오거나 또 다른 괄호의 시작 문자가 나올 때까지 문자형을 하나하나 더한 다음에 배열에 넣어준다. 여기서 주의할 점은 공백 문자도 단어에 포함해서 넣으면 reverse 할 때 같이 정렬되기 때문에 나는 공백 문자는 따로 배열에 넣어줬다. 이렇게 하면

 

1: "< space >"

2: "space" 

3: " "

4: "space"

5: " "

6: "space"

7: "< spa c e>"

 

이런 식으로 배열에 들어가게 되는 것이다. 그래서 이 배열들을 for문으로 한 바퀴 돌리면서 한 단어 안에 시작이 '<' 끝이 '>'인 단어를 제외하고 전부 단어를 뒤집어 주면 해결되는 것이다.

 

 

3. 코드 설명

 

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

int main()
{
    int i = 0, f = 0;
    string s, t = "";
    vector<string> v;

    getline(cin, s);

    while(i != s.size())
    {
        if (s[i] == '<')
        {
            while(s[i] != '>')
                t += s[i++];
                
            t += s[i++];
            v.push_back(t);
            t = "";
        }
        else
        {
            while(s[i] != ' ')
            {
                t += s[i++];
                if (s[i] == '<')
                {
                    i--;
                    f = 1;
                    break;
                }
                if (i == s.size() - 1)
                {
                    t += s[i];
                    f = 1;
                    break;
                }  
            }
            
            v.push_back(t);
            if (f == 0)
                v.push_back(" ");
            t = "";
            i++;
            f = 0;
        }
    }

    for (i = 0; i < v.size(); i++)
        if (v[i][0] != '<')
            if(v[i][v[i].size() - 1] != '>') 
                reverse(v[i].begin(), v[i].end());

    for (i = 0; i < v.size(); i++)
        cout << v[i];
}

 

 

일단 문자열을 s에 공백 포함해서 전부 받는다. 그냥 cin으로 받으면 공백 문자 단위로 잘리기 때문에 getline()을 이용한다.

while문으로 s를 한 바퀴 돌린다.

만약 '<'가 나오는 경우 '>'가 나올 때까지 문자열 t에 값을 저장한다. 이때 while문은 '>' 전에 멈추기 때문에 마지막에 한 번 더 문자형을 저장해준다. 그리고 t를 재활용하기 위해 초기화해준다.

태그 안에 있는 단어가 아닌 경우는 공백 문자로 구분되거나 새로운 태그가 나오기 전까지로 구분된다. 그리고 잊지 말아야 하는 게 공백도, 태그도 아닌 문자열이 끝났을 때도 단어가 끝난다는 사실을 잊으면 안 된다.

else문에서 이 세 가지 케이스를 처리해준다. 이때 if문 때문에 값이 덜 들어갈 수도 있고 더 들어갈 수도 있기 때문에 index 조절을 잘해줘야 한다. f는 공백 문자를 넣을지 말지 판별하는 용도로 사용했다. 

reverse함수로 각 배열에 넣어진 단어들을 뒤집어서 출력해줬다. 이때 태그들은 뒤집으면 안 됐기 때문에 if문을 걸었는데 한 if문에 두 개 걸고 or 했는데 뒷 조건이 자꾸 무시돼서 if문을 두 개 썼다. (우선순위 때문인지 뭔지... 모르겠음)

 

 

 

+ 자바로 다시 풀었다!!

 

https://coding-log.tistory.com/172

 

[JAVA] 백준 17413 단어 뒤집기 2

https://www.acmicpc.net/problem/17413 ')로만 이루어져 " data-og-host="www.acmicpc.net" data-og-source-url="https://www.acmicpc.net/problem/17413" data-og-url="https://www.acmicpc.net/problem/17413"..

coding-log.tistory.com

 

 

 

반응형

'Algorithm' 카테고리의 다른 글

[C++] 백준 2606 바이러스  (0) 2021.07.29
[C++] 백준 16956 늑대와 양  (0) 2021.07.10
[C++] 백준 7568 덩치 (+Python)  (0) 2021.06.04
[C++] 백준 2231 분해합  (0) 2021.06.04
[C++] 백준 2480 주사위 세개, 2484 주사위 네개  (0) 2021.05.10
myoskin