题目大意
解题思路
如果所有询问长度都一样的话,o(n)就能解决,开个桶随便记录一下就可以了。那么我们按长度排序,发现长度不同的数量不会超过根号n个,等差数列求和,这样我们就可以解决了。
code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define min(a,b) ((a<b)?a:b)
#define max(a,b) ((a>b)?a:b)
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std ;
int const maxn=2 *1e5 ;
int q,sum[maxn+10 ],ans[maxn+10 ],cnt[maxn+10 ];
struct rec{
int pos,len,val;
};
rec a[maxn+10 ];
char s[maxn+10 ],s1[maxn+10 ];
bool cmp(rec x,rec y){
return x.len<y.len;
}
int main(){
freopen("c.in" ,"r" ,stdin);
freopen("c.out" ,"w" ,stdout);
scanf ("%s" ,s+1 );
int lens=strlen (s+1 ),top=0 ;
fo(i,1 ,lens)sum[i]=sum[i-1 ]+(s[i]=='1' );
scanf ("%d\n" ,&q);
fo(cas,1 ,q){
scanf ("%s\n" ,s1+1 );
int lens1=strlen (s1+1 ),tmp=0 ;
fo(i,1 ,lens1)tmp+=(s1[i]=='1' );
a[++top].pos=cas;
a[top].len=lens1;
a[top].val=tmp;
}
sort(a+1 ,a+q+1 ,cmp);
int i=1 ,j;
while (i<=q){
j=i;
for (;(a[i].len==a[j+1 ].len)&&(j+1 <=q);j++);
fo(k,0 ,lens)cnt[k]=0 ;
fo(k,a[i].len,lens)cnt[sum[k]-sum[k-a[i].len]]++;
fo(k,i,j)ans[a[k].pos]=cnt[a[k].val];
i=j+1 ;
}
fo(i,1 ,q)printf ("%d\n" ,ans[i]);
return 0 ;
}