BOJ 24978 - Subset Equality

image.png

개인적으로 아이디어는 금방 보였다.

$a \sim r$은 $18$개밖에 안되기 때문에 $18^2(Q+N)$ 정도로 풀 수 있다.

가능한 모든 경우에 대해 미리 전처리를 해두는 것이다.

만약 $s$와 $t$에 각각 어떤 알파벳 $c$가 서로 다른 횟수가 나온다면 그 알파벳이 들어가면 항상 불가능하다.

그렇지 않고 $A, B$가 서로 다른 알파벳이라고 하자.

문자열에서 A의 개수와 B의 개수를 본다.

더 작은 것을 쭉 순회하며 나머지 인덱스들의 위치가 이분탐색을 해서 $s,t$ 모두 같게 나오면 그 문자 두개는 같이 나와도 문제가 없다.

이런 최적화는 필요가 없긴 하다.

여러 문자가 같이 set에 있을 때 아무 두 문자에 대해 모두 만족해야 하는것이 필요충분조건이라 $O(18^2)$에 검사해줄 수 있다.

$\vert s \vert \neq \vert t \vert$ 인 경우도 가능하다는 것을 주의한다.

int ok[18][18];
void solve() {
   for (int i = 0; i < 18; i++) for (int j = 0; j < 18; j++) ok[i][j] = 1;
   string s, t;
   cin >> s >> t;
   int q;
   cin >> q;
   vvi idxs(18), idxt(18);


   for (int i = 0; i < sz(s); i++) {
      idxs[s[i] - 'a'].pb(i);
   }
   for(int i = 0 ;i < sz(t); i++) {
      idxt[t[i] - 'a'].pb(i);
   }
   for (int i = 0; i < 18; i++) {
      if (sz(idxs[i]) != sz(idxt[i])) {
         for (int j = 0; j < 18; j++) ok[i][j] = ok[j][i] = 0;
      }
   }
   for (int i = 0; i < 18; i++) {
      for (int j = 0; j < 18; j++) {
         if (!ok[i][j]) continue;
         int I = i, J = j;
         if (sz(idxs[I]) > sz(idxs[J])) swap(I, J);
         for (int i1 = 0; i1 < sz(idxs[I]); i1++) {
            int chk1 = lbi(idxs[J], idxs[I][i1]);
            int chk2 = lbi(idxt[J], idxt[I][i1]);
            if (chk1 != chk2) {
               ok[i][j] = ok[j][i] = 0;
               break;
            }
         }
      }
   }

   for (int i = 0; i < q; i++) {
      vi idx;
      string s;
      cin >> s;
      for (char c: s) idx.pb(c - 'a');
      int yes = 1;
      for (int c1: idx) for (int c2: idx) if (!ok[c1][c2]) yes = 0;
      if (yes) cout << 'Y';
      else cout << 'N';
   }
}

Tags:

Categories:

Updated:

Comments