【競プロ精進ログ】ABC143-C

zuka

ABCをコツコツ解いていきます。

本記事は,管理人の競技プロ精進日記としてログを取ったものです。モチベーションを爆上げするために,積極的にアウトプットしていく作戦です。これから競技プログラミングを始めようと考えている人や,なんとなく敷居が高いと感じている人の参考になれば嬉しく思います。その他の記事は以下をご覧ください。

目次

本記事の概要

Atcoderで初心者用のコンテストとして開催されているAtcoder Beginner Contest(通称ABC)を解いていくものです。今回はABC143-C「Slimes」です。

ポイント

重複要素を削除するunique関数をerase関数と一緒に活用できるかという問題です。以下で詳しく説明します。

おさえるべき内容

 unique関数とerase関数の活用

unique関数

c++公式日本語リファレンス:std::unique

unique関数には,対象文字列の先頭部分のイテレータと末尾のイテレータを渡します。すると,渡された文字列は重複要素が削除され,削除した文字数分末尾に適当な文字が追加された文字列になります。難しい日本語になってしまったため,具体例を示します。

例えば,aabbccunique関数に渡すと,aabbccabcbccのような文字列になります。この文字列は,いわばabc???と捉えられます。つまり,aabbccの重複を削除したabcと,削除した文字数分である3文字だけ適当な文字???を追加した文字列とみなせます。

unique関数は,戻り値として?の先頭のイテレータ(ポインタ)を返します。実際にコードでみていきましょう。

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

string S;

int main(){
  cin >> S;
  // 戻り値はイテレータなのでautoもしくはstring::iteratorで宣言
  // uniqueの引数には対象文字列の先頭と末尾のイテレータを渡す
  auto itr = unique(S.begin(), S.end());
  // Sがaabbccのとき,ここではabcbcc(abc???)となっている
  cout << S << endl;
  // 戻り値のイテレータが示すのは?の最初のイテレータなのでbとなる
  cout << *itr << endl;
}

erase関数

c++公式日本語リファレンス:std::erase

続いて,erase関数です。erase関数は,unique関数同様に,対象文字列の先頭のイテレータと末尾のイテレータを渡します。すると,対応する文字列が削除されます。戻り値としては,削除された要素の次の要素を指すイテレータになります。

#include <bits/stdc++.h>
#define _GLIBCXX_DEBUG
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
using namespace std;

string S;

int main(){
  cin >> S;
  // 先頭から2文字を削除
  auto itr = S.erase(S.begin(), S.begin()+2);
  // Sをaabbccとするとbbccとなる
  cout << S << endl;
  // 戻り値は削除した要素の次の要素を指すイテレータなのでbになる
  cout << *itr << endl;
}

実装

unique関数とerase関数を組み合わせれば,以下のような実装が考えられます。

#include <bits/stdc++.h>
#define _GLIBCXX_DEBUG
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
using namespace std;

int N;
string S;

int main(){
  cin >> N >> S;
  string::iterator itr = unique(S.begin(), S.end());
  S.erase(itr, S.end());
  cout << S.size() << endl;
}

もう少し綺麗に書くと,以下のようになります。

#include <bits/stdc++.h>
#define _GLIBCXX_DEBUG
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
using namespace std;

int N;
string S;

int main(){
  cin >> N >> S;
  S.erase(unique(S.begin(), S.end()), S.end());
  cout << S.size() << endl;
}
よかったらシェアしてね!

コメント

コメントする

目次
閉じる