ABC249 C - Just K
キーワード
ビット全探索
ビット演算
シフト演算
キーワードについて解説していきます
シフト演算
見やすさ重視でバイナリ表記で出力していますが、下記コードは右シフトの演算です
例:0010 >> 0001 = 00001, 1000 >> 0010 = 0010
演算子の右側にある1が見えなくなるまでずらしていき、
同じ分だけ、左側もずらされる
for i in range(1,4): for j in range(3): print(bin(i>>j)) >>> 0b1 # 0b1 >> 0b0 0b0 # 0b1 >> 0b1 0b0 # 0b1 >> 0b10 0b10 # 0b10 >> 0b0 0b1 # 0b10 >> 0b1 0b0 # 0b10 >> 0b10 0b11 # 0b11 >> 0b0 0b1 # 0b11 >> 0b1 0b0 # 0b11 >> 0b10
ビット演算 ( &のみ )
&演算子は、お互い1の時のみ1を返します
例:0001 & 0001 = 0001, 1010 & 1010 = 1010, 0101 & 1001 = 0001
※ and(論理演算子)で&(ビット演算子)となり別物
print(bin(7&3)) # 0b111 & 0b11 >>> 0b11
ビット全探索
3つのうち、2パターンの合計は2^3(1<<3) = 8通り
2パターンとはバイナリの0と1、つまり選ぶ( 1 )か選ばない( 0 )か
これを使って、N個の文字列から好きな個数を選択するための全通りが行える
for i in range(1<<3): for j in range(3): print(bin(i>>j & 1)) >>> 0b0 0b0 0b0 0b1 0b0 0b0 0b0 0b1 0b0 0b1 0b1 0b0 0b0 0b0 0b1 0b1 0b0 0b1 0b0 0b1 0b1 0b1 0b1 0b1
解答
キーワードに関する説明は省くとして、
アルファベットの配列(a = 0 を起点とする,)に、選択した文字列に含まれる単語をカウントしていく
配列の要素つまりカウント数が==Kとなっている数が一番多い時をansに記憶しておく
N, K = map(int, input().split()) S = [input() for _ in range(N)] ans = 0 for i in range(1<<N): alph = [0]*26 cnt = 0 for j in range(N): if i>>j & 1: for k in S[j]: alph[ord(k)-ord('a')] += 1 for j in range(26): if alph[j] == K: cnt += 1 ans = max(ans, cnt) print(ans)
参考
bit 全探索 - けんちょんの競プロ精進記録
ビット演算 (bit 演算) の使い方を総特集! 〜 マスクビットから bit DP まで 〜 - Qiita