[伯俊]146号編集


これもGDSCチームブログで発表された問題です!
https://gdsc-seoultech.github.io/posts/2021-10-14-python_1406/
https://www.acmicpc.net/problem/1406

問題を要約すると以下のようになる.
Lカーソルを左に移動
Dカーソルを右に移動
Bカーソル左側の文字を削除する
Pカーソル左側に文字を追加

接続リストを使用して解く


1.アルゴリズムの理解


まずlistコンテナの基本的な使い方を理解します.
https://blockdmask.tistory.com/76
特に注目すべきは,end()とinsert()である.endは最後の要素の次の位置を指し、insertは指定した位置の直前に要素を挿入します!
https://www.cplusplus.com/reference/list/list/insert/
The container is extended by inserting new elements before the element at the specified position.
与えられた問題の最初の例入力で練習しましょう.

  • 文字列abcdを入力すると、接続リストが初期化されます.


  • Px(カーソル左側にxを挿入)


  • L(カーソルを左に移動)


  • Py(カーソル左側にyを挿入)

  • 2.コード実装

    #include <iostream>
    #include <string>
    #include <list>
    using namespace std;
    
    int main() {
        string s;
        cin >> s;
    
        // 문자 하나씩 연결리스트에 추가
        list<char> l(s.begin(), s.end());
    
        //list<char>::iterator now = l.end();
        auto cur = l.end();
        // end()는 마지막 원소 바로 다음 위치를 가리킴.
    
        int n;
        cin >> n;
    
        while (n--) {
            char cmd;
            cin >> cmd;
    
            if (cmd == 'L') { 
                if (cur != l.begin()) {
                    cur--; // 왼쪽 이동
                }
            }
            else if (cmd == 'D') { 
                if (cur != l.end()) {
                    cur++; // 오른쪽 이동
                }
            }
            else if (cmd == 'B') {
                if (cur != l.begin()) {
                    cur = l.erase(--cur);
                    // 커서의 왼쪽 원소 삭제
                }
            }
            else if (cmd == 'P') {
                char c;
                cin >> c;
                l.insert(cur, c); 
                // 커서의 바로 앞부분에 삽입
            }
        }
    
        /*for (auto it = l.begin(); it != l.end(); it++) {
            cout << *it;
        }*/
        for (auto& e : l) { // 범위 기반 for문
            cout << e;
        }
    
        return 0;
    }

    新しい解答:スタックの使用


    1.コアクリエイティブ


    https://intaehwang.tistory.com/32
  • カーソルを基準として、左側スタック、右側スタックを宣言します.
  • Lの場合、左側スタックの上部を右側スタック
  • に押す.
  • Dの場合、右側スタックの上部を左側スタック
  • に押す.
  • Bの場合、左側スタックtopはpop
  • とする.
  • Pであれば左側スタックに
  • をプッシュする.
    出力
  • の場合、左側スタック全体を
  • 右に押す.
    右スタック
  • 全体がポップアップされ、
  • が出力されます.
    カーソルによって左右のスタックをそれぞれ作成するアイデア!カーソルは常に2つのスタック間を指し、カーソルの移動は左スタック要素と右スタック要素間の挿入と削除操作で表すことができます.
    さっきと同じように、与えられた問題の最初の例入力で練習しましょう.

  • 入力文字列abcd(左側のスタックに1文字をプッシュ)


  • Px(xを左側のスタックにプッシュ)


  • L(カーソルを左に移動し、左側のスタックの上部を右側のスタックに押します)


  • Py(yを左側のスタックに押し込む)

  • 最終結果

    2.コード実装

    #include <iostream>
    #include <stack>
    #include <string>
    using namespace std;
    
    int main() {
        string s;
        cin >> s;
    
        stack<char> l;
        stack<char> r;
    
        // 왼쪽 스택에 입력된 모든 문자를 push
        for (int i = 0; i < s.size(); i++) {
            l.push(s[i]);
        }
    
        int num;
        cin >> num;
        while (num--) { // num == 0이면 종료
            char cmd;
            cin >> cmd;
    
            // P: 왼쪽 스택의 top에 추가
            if (cmd == 'P') {
                char c;
                cin >> c;
                l.push(c);
            }
            // B: 왼쪽 스택이 비어있지 않다면, 왼쪽의 top 삭제
            else if (cmd == 'B') {
                if (l.empty()) continue;
                else l.pop();
            }
            // L: 왼쪽 스택이 비어있지 않다면, 왼쪽의 top을 오른쪽에 push
            else if (cmd == 'L') {
                if (l.empty()) continue;
                else {
                    r.push(l.top());
                    l.pop();
                }
            }
            // D: 오른쪽 스택에 비어있지 않다면, 오른쪽의 top을 왼쪽에 push
            else if (cmd == 'D') {
                if (r.empty()) continue;
                else {
                    l.push(r.top());
                    r.pop();
                }
            }
        }
    
        // 왼쪽 스택 전체를 오른쪽 스택에 push
        while (!l.empty()) {
            r.push(l.top());
            l.pop(); // LIFO
        }
    
        // 오른쪽 스택 전체 출력 (LIFO)
        while (!r.empty()) {
            cout << r.top();
            r.pop(); // LIFO
        }
    
        return 0;
    }

    Pythonプール

    from sys import stdin
    
    left = list(stdin.readline().strip())
    right = []
    n = int(input())
    
    for _ in range(n):
        temp = stdin.readline()
        if temp[0] == 'L':
            if len(left) == 0:
                continue
            right.append(left.pop())
        elif temp[0] == 'D':
            if len(right) == 0:
                continue
            left.append(right.pop())
        elif temp[0] == 'B':
            if len(left) == 0:
                continue
            left.pop()
        elif temp[0] == 'P':
            left.append(temp[2])
    
    # 오른쪽 리스트 원소들의 순서를 뒤집어서 왼쪽 리스트에 붙이고 전체 출력
    #right.reverse()
    #left.extend(right)
    left.extend(right[::-1])
    
    print("".join(left))