[AtCoder]ABC B042 – 文字列大好きいろはちゃんイージー [C++]

プログラミング

今回から、B問題を解いていきます。しょっぱなから躓いていて、A問題のようにサクサクいきません。全て解き終わるのは、いつになることやら、、、。

ABC B042 – 文字列大好きいろはちゃんイージー

問題

いろはちゃんは 長さLの文字列をN個持っており、それぞれS1,S2,…,SNです。
それらの文字列を好きな順番で全て結合してできる文字列のうち、もっとも辞書順で小さいものを求めてください。
なお、ある文字列 s=s1s2s3…snとt=t1t2t3…tmについて、以下のどちらかを満たすとき、辞書順比較で s<tであるといいます。

  • ある整数 i(1≦i≦min(n,m))に関して、1≦j<iを満たす任意の整数jにおいてsj=tjが成立し、かつ si<tiが成立する。
  • 任意の整数 i(1≦i≦min(n,m))に関してsi=tiが成立し、かつn<mが成立する。

自分の回答

#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int N, L;
  cin >> N >> L;

  vector<string> words{};

  for (int i = 0; i < N; i++) {
    string S;
    cin >> S;
    words.emplace_back(S);
  }
  
  sort(words.begin(), words.end());

  string ans;
  for (int i = 0; i < N; i++) {
    ans += words[i];
  }
  
  cout << ans << endl;
}

C++でB問題を初めてときましたが、さすがB問題、一筋縄ではいきません。早速新しい、関数もでてきました。しかし、エラーも起こさず、一発で正解することができました。嬉しい!

まず最初に、wordsというベクターを用意します。これは、入力される文字列Sを格納して、辞書順に並べるためです。
forを使って入力を受け付け、順番にwordsベクターに格納していきます。ベクターへの格納にはemplace_back関数を使っています。forを使って入力を受け付けるのも知らないとできないですよね。
次にソートして、辞書順に並べます。
最後に、文字列を一つずつ取り出して、ansという変数に結合していきます。数値と同じように“+”を使えば、文字列でも簡単に結合できます。

emplace_back関数
vectorの末尾に要素を追加します。同じような動作をするものにpush_back関数がありますが、emplace_back関数の方が若干処理が早いみたいです。

もっとよくする

#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int N, L;
  cin >> N >> L;

  vector<string> words(N);

  for (int i = 0; i < N; i++) {
    cin >> words.at(i);
  }

  sort(words.begin(),words.end());

  for(s : words){
    cout << s;
  }
  cout << endl;
}

他の人のを参考にして、修正しました。

修正点はまずは、文字列の入力のところですね。自分はいちいち変数を宣言していたのですが、直接ベクターに格納していますね。こちらの方が、面倒臭いことしなくていいですね。
あとは、出力のところですね。自分は、足し合わせてから出力していましたが、forの中にcoutを組み込んで、出力していますね。なるほど、こんな方法もあるのですね。for文の新しい書き方も出てきました。

範囲for
範囲forとは、配列、ベクターなどの要素数があるものの全要素に対して処理を行うものです。全要素に処理を行いたい時は通常のfor文より簡潔にコードが書けます。

for(変数宣言 : 範囲(配列)){
    //処理内容
}

ABC 043B – バイナリハックイージー

問題

しぐはキーボードを製作しました。シンプルさを極限まで追求したこのキーボードには、0 キー、1 キー、バックスペースキーの3つしかキーがありません。

手始めに、しぐはこのキーボードで簡単なテキストエディタを操作してみることにしました。このエディタには常に一つの文字列が表示されます(文字列が空のこともあります)。エディタを起動した直後では、文字列は空です。キーボードの各キーを押すと、文字列が次のように変化します。

  • 0 キー: 文字列の右端に文字 0 が挿入される。
  • 1 キー: 文字列の右端に文字 1 が挿入される。
  • バックスペースキー: 文字列が空なら、何も起こらない。そうでなければ、文字列の右端の1文字が削除される。

しぐはエディタを起動し、これらのキーを何回か押しました。しぐが押したキーを順番に記録した文字列 ss が与えられます。sの中の文字 0 は 0 キー、文字 1 は 1 キー、文字 B はバックスペースキーを表します。いま、エディタの画面にはどのような文字列が表示されているでしょうか?

自分の回答

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

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

  string ans ="";

  for (int i = 0; i < s.length(); i++) {
    if(s[i] == '0'){
      ans += "0";
    }else if(s[i] == '1'){
      ans += "1";
    }else if(s[i] == 'B' && ans.length() != 0){
      ans.erase(ans.length() - 1);
    }
  }

  cout << ans << endl;
}

先頭から一文字ずつ取り出して、if文によって条件分岐させればいいですね。
ans.length() – 1で文字列の最後尾の文字を削除しています。この時注意しなければいけないのは、条件にans.length() != 0を入れているところです。ansの長さが0の時、ans.length() – 1の値がマイナスとなってしまうので、ansが空っぽの時は、eraseをしないようにしないといけません。
また、自分が引っかかった箇所は、s[i] == ‘0’の部分を”0″シングルクォーテーションではなく、ダブルクォーテーションにしていて、エラーになりました。
C++では文字と文字列では別と判断しているようです。シングルクォーテーションは文字、ダブルクォーテーションは文字列となるため、エラーになっていたようです。詳しくは別記事に書きます。

// OK
if(s[i] == '0'){
      ans += "0";
}
//error
if(s[i] == "0"){
      ans += "0";
}
タイトルとURLをコピーしました