问题传送门
有n个长度为m的文本串,每个串只含有’0’和’1’。接下来有Q次询问,每次给出一个长度为m的字符串,且只含有’0’,‘1’和’_’。如10_1_1。下划线可以匹配’0’或’1’。即10_1_1可以匹配101111,101101,100111,100101四种串。每次询问求出n个文本串中有多少个可以与当前询问的串匹配。
输入描述:
第一行输入n,m
接下来n行,每行输入一个长度为m的01串表示一个文本串。
第n+2行输入Q
接下来Q行,每行输入一个长度为m的字符串(只包含’0’,‘1’,’_’)。
1<=n,m<=1000,1<=Q<=3000。
输出描述:
对于每次询问,输出n个文本串中有多少个与当前询问的串匹配。
示例1
输入
5 6
101101
011011
100110
111000
101111
2
1011_1
1__1__
输出
2
3
说明
第一次询问:有101101,101111与1011_1匹配
第二次询问:有101101, 100110, 101111与1__1__匹配
分析
多次查询问题,一般是多查询过程比较耗时,本题中如果逐一字符比较一定会超时。利用bitset可减少,利用bitset位运算可直接比较字符串,bitset在一些情况时很好用,bitset可以看做一种特殊的数组。
if(s[i]=='_')
q[i]=p[i]=0;
else
{
q[i]=1,p[i]=s[i]=='1'?1:0;
}
这一部分是代码的主要部分,可以用例子模拟一下
#include<stdio.h>
#include<iostream>
#include<string>
#include<bitset>
using namespace std;
const int maxn=1e3+10;
bitset<maxn> b[maxn],p,q;
char s[maxn];
int main()
{
int n,m;
int x;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%s",s);
for(int j=0;j<m;j++)
{
if(s[j]=='1')
b[i][j]=1;
else
b[i][j]=0;
}
}
scanf("%d",&x);
while(x--)
{
int ans=0;
scanf("%s",s);
for(int i=0;i<m;i++)
{
if(s[i]=='_')
q[i]=p[i]=0;
else
{
q[i]=1,p[i]=s[i]=='1'?1:0;
}
}
for(int i=0;i<n;i++)
{
if((b[i]&q)==p)
ans++;
}
printf("%d\n",ans);
}
return 0;
}