Subset Equality (USACO Silver 2022 Open)
一遍扫描预处理两个数据结构:
count[2][x]
,字母x的个数mismatch(x,y)
, 字母x和y存在“错位”
有了这两个数据结构之后,就可以快速回答每个query了
- 所有字母的个数得一致。
- 两两之间不存在错位(最多18*18/2个字母对)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int q, slen, tlen;
char s[100005];
char t[100005];
int cnt[2][20];
bool mis[20][20]; // mismatches between letter pairs
int main() {
scanf("%s", s);
scanf("%s", t);
slen = strlen(s);
tlen = strlen(t);
// 预处理count
for (int i = 0; i < slen; i++)
cnt[0][s[i]-'a']++;
for (int i = 0; i < tlen; i++)
cnt[1][t[i]-'a']++;
// 预处理mismatch: two pointers
int pos[20][20] = {0}; // position of each {x,y} letter pair sub-stream in t
for (int i = 0; i < slen; i++) {
char a = s[i];
for (char b = 'a'; b <= 'r'; b++) {
if (a == b) continue;
int x = min(a,b)-'a', y = max(a,b)-'a';
if (mis[x][y]) continue; // already in mismatch
// if we find b instead of a as next char in t, we have mismatched
while (pos[x][y] < tlen && t[pos[x][y]] != a && t[pos[x][y]] != b)
pos[x][y]++;
if (pos[x][y] == tlen || t[pos[x][y]] == b)
mis[x][y] = true;
else
pos[x][y]++;
}
}
scanf("%d", &q);
for (int i = 0; i < q; i++) {
char p[20];
scanf("%s", p);
int plen = strlen(p);
bool ok = true;
for (int i = 0; i < plen; i++)
if (cnt[0][p[i]-'a'] != cnt[1][p[i]-'a']) {
ok = false;
break;
}
if (ok) {
// check all letter pairs for mismatches
for (int i = 0; i < plen; i++) {
for (int j = i+1; j < plen; j++)
if (mis[p[i]-'a'][p[j]-'a']) {
ok = false;
break;
}
if (!ok) break;
}
}
printf(ok ? "Y" : "N");
}
return 0;
}