Official

D - 書き換え/Replace Editorial by sugarrr


「左から順に見ていき、axa, ixi, uxu, exe, oxoのいずれかと一致する箇所があれば ... に書き換える」という貪欲法が正しい解法です。

なぜなら、書き換えた場合と敢えて書き換えなかった場合を比較して、敢えて書き換えなかったことで得をすることはないからです。

いくつか誤答例を紹介します。

「左から順に見ていき、axa, ixi, uxu, exe, oxoのいずれかと一致する箇所があれば ... に書き換える。書き換えたら、再度一番左からチェックする。」という実装方針を取ると、計算量は \(O(N^2)\) になりTLEします。

また、「ランダムな場所をチェックしaxa, ixi, uxu, exe, oxoのいずれかと一致する箇所があれば ... に書き換える。」という方針ではWAが出るはずです。例えば axaxaxa というケースで初めに ax...xa と書き換えてしまうと操作回数が最大にならないからです。

最初に述べた正しい方針で実装すると、次のようになります。計算量は \(O(N)\) です。

C++による実装例:

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

signed main(){
    ll n;string s;
    vector<string> T={"axa","ixi","uxu","exe","oxo"};
    cin>>n>>s;
    for(int pos=0;pos<=n-3;pos++){
        bool flag=false;
        string sub=s.substr(pos,3);
        for(auto t:T){
            if(sub==t)flag=true;
        }
        if(flag){
            s[pos]=s[pos+1]=s[pos+2]='.';
        }
    }
    cout<<s<<endl;
    return 0;
}

posted:
last update: