Official

C - ユニークな座席 / Unique Seats Editorial by kyopro_friends


各マスに対して愚直に同じ行・列の文字を調べると、同じ文字が見つかった時点で探索を打ち切るとしても、最悪ケースでは全体で \(\Theta(HW(H+W))\) 時間がかかります。

予め各行・各列にどの文字が何度登場するかを調べて辞書で保持しておき、「この行にこの文字は何個あるか?」を \(O(\log (H+W))\)\(O(1)\) で求められるようにしておくことで、この問題を \(O(HW\log (H+W))\)\(O(HW)\) で解くことができます。

実装例 (C++)

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

int main(){
  int h, w;
  cin >> h >> w;
  vector<string>s(h);
  for(int i=0; i<h; i++) cin >> s[i];

  vector<map<char,int>>tate_count(h);
  vector<map<char,int>>yoko_count(w);
  for(int i=0; i<h; i++)for(int j=0; j<w; j++){
    tate_count[i][s[i][j]]++;
    yoko_count[j][s[i][j]]++;
  }

  for(int i=0; i<h; i++)for(int j=0; j<w; j++){
    if(tate_count[i][s[i][j]] == 1 && yoko_count[j][s[i][j]] == 1){
      cout << s[i][j];
    }
  }
}

実装例 (Python)

from collections import Counter
H, W = map(int, input().split())
S = [input() for _ in range(H)]
tate_count = [Counter(S[i]) for i in range(H)]
yoko_count = [Counter(S[i][j] for i in range(H)) for j in range(W)]

for i in range(H):
  for j in range(W):
    if tate_count[i][S[i][j]] == 1 and yoko_count[j][S[i][j]] == 1:
      print(S[i][j], end="")

posted:
last update: