C. 富豪凱匹配串
題目
給出 n 個長度爲 m 的 01 串,有 q 次詢問,每次給出一個長度 m 的字符串(只有 0,1,_),問之前 n 個串有多少可以匹配?( _ 可以匹配 0 或者 1)
n, m <1e3, q < 3e3
分析
考慮每次都把 n 遍歷完(Onmq)肯定會超時。因此要優化每次的匹配過程。
這裏用兩個數組,ones[i][[j] 如果爲 1,表示第 j 個串的 i 位置爲 1。也就是說,如果想知道 i 位置有 0到n 的哪些串是 1,就看一下 ones[i] 這個數組即可。zeros 同理
做法:遍歷 m 位置,ans[i] 存還有多少滿足要求,每次迭代從 ans 種選出滿足當前位置要求的,最後剩下來就是滿足所有位置要求的。( 利用位運算 & 可以將每次 n 的遍歷優化到 O1。)
代碼
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define fuck(x) cout<<x<<endl
const int N = 1e3 + 10;
const ll mod = 1e9 + 7;
int n, m, q;
char str[N][N], c[N];
bitset<N> ans, ones[N], zeros[N]; //ones[i] 表示 i 位置是 1 的下標
int main(){
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++){
scanf("%s", str[i]);
for(int j = 0; j < m; j++){
if(str[i][j] == '1')
ones[j][i] = 1;
else
zeros[j][i] = 1;
}
}
scanf("%d", &q);
while(q--){
scanf("%s", c);
ans.set(); // ans[i] 爲 1 表示 i 號串滿足要求
for(int i = 0; i < m; i++){
if(c[i] == '1')
ans &= ones[i];
if(c[i] == '0')
ans &= zeros[i];
}
printf("%d\n", ans.count()); // 數下有多少滿足要求
}
return 0;
}