genzai0の日記

にっき

abc137cのノート

近況

前回から一か月近く経った。

一か月ほど帰省している。

本を数冊読んだ。競プロから離れていたし、コンテストにも出ていなかった。なるべくコンテストにはい。

ディープラーニングがわかる数学入門を一応読み終えた。数学に関してあまり明るくないので、かなり躓き苦しみながら読んだが、どうにか糧にできたと思いたい。

abc137c

某ゴリラ競プロerを解答を参考にした。abcでpython書きでほぼ毎回最速acをもぎ取っているので見習いたい…

今回の学びとして、Counter()について先に述べる。

dict型とcollections.Counter()

collections型は以下の公式ドキュメントを参照した

docs.python.org

今回使用したのはdict型でのバグを減らす目的である。

当たり前だが、バグるコード。

d = {}
d["k"] += 1

dict型なので勿論怒られる。

「"k"なんてkey見つかんないんだけどっ!」ってpythonちゃんにたしなめられてしまう。

しかし、

from collections import Counter
c = Counter()

c["k"] += 1

このようにCounter()を用いると辞書型風にカウントしてくれて、さらに怒られない。 名前の通り、そのまま単語のカウンターとして機能してくれる。

また、標準ライブラリなのでどこでも使える。

パクったコード

わからなかったのでパクった。

# original_author prd_xxx
from collections import Counter

N = int(input())
S = [input() for i in range(N)]

# collections.Counter()を使うと0回目の時にバグらないのでelseを省略可能
# ctr = Counter()
ctr = {}
ans = 0

for s in S:
    a = ''.join(sorted(list(s)))

    if a in ctr:
        ans += ctr[a]
    else:
        ctr[a] = 0

    ctr[a] += 1

print(ans)

ソート済み文字列が以前に存在していたら、答えに前回の合計値を加算する。

もし仮に同様の文字列(ここでは1文字)が処理されたらansは1回目..0加算(合計0) 2..+1(1) 3..+2(3) 4..+3(6) 5..+4(10)の増加になる。

更新手順について、自分の考えていたのは最後に出現回数をそれぞれで計算し、 その個数分をそれぞれ算出しようと思っていたが解法をみて要らない手間だと感じた。 (アナグラムが同様のグループに含まれる個数が同じものについては計算できるからそれを優先しようと思考していた)

丸パクリだと何となく嫌なので、辞書型に組み替えた。