Yuulis.log

Yuulis.log

トンネルを抜けるとそこは参照エラーであった。

【AtCoder】ABC 394 C - Debug | 緑コーダーが解くAtCoder

atcoder.jp

配点: 300 点 / 実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 161

問題概要

英大文字のみからなる文字列  S が与えられるので、  S に対して、次の手順を行った後に得られる文字列を出力せよ。

  • 文字列がWAを部分文字列として含む限り、次の操作を繰り返す。
    • 文字列中に登場するWAのうち最も先頭のものをACに置換する。

制約

  •  S の長さは  1 以上  3\times 10^5 以下。

考察

基本的には、「 S の先頭から1文字ずつ見ていって、直近の2文字がWAであればACに置き換える」とすればよい。

しかし、サンプルケース2のように、  S i 文字目にWが存在する場合、  i+1 文字目と  i+2 文字目にまたがるWAACに置き換えた後、連鎖的に置き換えが発生することに注意する必要がある。


ということで、stack再帰関数を用いて実装していく。具体的なアルゴリズムは以下の通り。


  1. 空のstackを用意する。
  2. 再帰関数  f(c) \: (cは次に追加する文字 ) を以下のように定義する。
    1. もしstackが空なら、そのまま  c を追加して終了。
    2. もしstackの先頭がWかつ  c =Aならば、先頭要素をpopした後  f(A  ) f(C  ) を実行して終了。
    3. それ以外のとき、そのまま  c を追加して終了。
  3.  f(S_i) \: (i = 1, 2, \cdots, N) を順に実行する。

実装例

#include <bits/stdc++.h>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)

// ======================================== //

void f(stack<char> &st, char c)
{
    if (st.empty())
    {
        st.push(c);
        return;
    }

    if (st.top() == 'W' && c == 'A')
    {
        st.pop();
        f(st, 'A');
        f(st, 'C');
        return;
    }

    st.push(c);
    return;
}

int main()
{
    string S;
    cin >> S;

    stack<char> st;
    rep(i, 0, S.size())
    {
        f(st, S[i]);
    }

    string ans = "";
    while (!st.empty())
    {
        ans += st.top();
        st.pop();
    }
    reverse(all(ans));
    cout << ans << endl;

    return 0;
}

atcoder.jp

実装時間: 10分

コメント

これとほぼ同じ要領で、 ABC351-C も解くことができる。

yuulis.hatenablog.com