Official

B - 2文字 / Two Letters Editorial by physics0523


今回の問題は、以下の手順で正解することができます。

  1. \(S\) の隣接 \(2\) 文字を抜粋した文字列を列挙する
  2. その中で最も高頻度なものを選ぶ(複数ある場合は辞書順最小のものを選ぶ)

言語によっていろいろ実装方法はありますが、今回は C++ で map を用いて実装する場合において詳細を説明します。

ポイント: map(連想配列) を利用する

map<string,int>string 型を key 、 int 型を value とする連想配列です。配列の添え字を文字列にしたものという理解をするとスムーズです。
例えば、 mp["apple"]=5; cout << mp["banana"]+mp["carrot"] << "\n"; というように利用できます(もちろん、添え字となる文字列が string 型の変数となっても構いません。)
なお、 int 型を value とする map は特に指定のない限り 0 で初期化されるので、今回のような問題を文字列のバケットソートのように取り扱うことができます。
map の中に詰まった要素を全部参照したい場合は、範囲 for 文が便利です。

#include<bits/stdc++.h>

using namespace std;

int main(){
  map<string,int> mp;
  mp["carrot"]=3;
  mp["apple"]=5;
  mp["banana"]=2;
  
  for(auto &nx : mp){
    cout << nx.first << ' ' << nx.second << '\n';
  }
  return 0;
}

を実行すると、

apple 5
banana 2
carrot 3

という結果になります。
範囲 for 文内で map<string,int> 内の要素は pair<string,int> として与えられ、さらに key が昇順ソートされた状態で参照することができます。
以上の特性をフルに利用した実装が、以下の実装例です。
実装例(C++)

#include<bits/stdc++.h>

using namespace std;

int main(){
  string s;
  cin >> s;
  int l=s.size();
  map<string,int> mp;
  for(int i=1;i<l;i++){
    string cur;
    cur.push_back(s[i-1]);
    cur.push_back(s[i]);
    mp[cur]++;
  }
  string res="";
  for(auto &nx : mp){
    if(mp[res]<nx.second){
      res=nx.first;
    }
  }
  cout << res << '\n';
  return 0;
}

posted:
last update: