Official

B - Frequency Editorial by evima


題意を再掲します。

  • 文字列 \(S\) に最も多く出現する文字のうちアルファベット順で最も早いものを出力せよ。

方針 1. for ループ

以下の処理を実装しましょう。

  1. a から z までの各文字の個数を保持する何らかのデータ構造 \(a\) を宣言し、すべての文字の個数を \(0\) とする。
  2. \(S\) の各文字 \(c\) について以下を行う:
    • \(a_c\)\(1\) を足す。
  3. 変数 \(\mathrm{ans}\) を宣言し、a を代入する。
  4. b から z までの各文字 \(c\) について(b, \(\dots\), z の順に)以下を行う:
    • \(a_c\)\(a_\mathrm{ans}\) より大きければ、\(\mathrm{ans}\)\(c\) を代入する。
  5. \(\mathrm{ans}\) の値を出力する。

「何らかのデータ構造」として使えるものには以下があります。

  • 連想配列(C++ の map や unordered_map、Python の dict など)
  • 通常の配列(a, \(\dots\), z を ASCII 値 \(97, \dots, 122\) として扱う)

以下に C++ での実装例を示します。(文字コードが ASCII であることを仮定します。これは競技プログラミングでは安全な仮定です。)

#include <iostream>
using namespace std;

int main() {
    string S;
    cin >> S;
    int a[128] = {};
    for (char c: S) {
        ++a[c];
    }
    char ans = 'a';
    for (char c = 'b'; c <= 'z'; ++c) {
        if (a[c] > a[ans]) {
            ans = c;
        }
    }
    cout << ans << endl;
}

方針 2. ライブラリ

言語によっては、文字列中の文字の出現回数を数えるライブラリ関数があり、方針 1 のひとつ目の for ループの部分の代わりになります。以下に Python の関数 count を使った実装例を示します。

S = input()
ans = 'a'
for i in range(ord('b'), ord('z') + 1):
    c = chr(i)
    if S.count(c) > S.count(ans):
        ans = c
print(ans)

\(S\) を何周もしていますが、短いので問題ありません。)

方針 1 のふたつ目の for ループにもライブラリ関数を代用することができます。ただし、タイブレークがアルファベットの昇順である点に注意を要します(例えば Python の Counter.most_common のタイブレークは初出順であり、残念ながらこれだけでは不十分です)。以下に Python のクラス Counter と関数 max を使った実装例を示します。

from collections import Counter

S = input()
print(max(Counter(S).items(), key=lambda x: (x[1], -ord(x[0])))[0])

posted:
last update: