正题
题目链接:http://noip.ybtoj.com.cn/contest/105/problem/2
题目大意
一个 01 01 01串, q q q个询问,每次询问有多少个长度为 m m m的子串 01 01 01个数与给出的 01 01 01串 T T T相同
解题思路
因为询问串的总长与
n
n
n同级,所以考虑根号分治
将询问的
T
T
T串长度分为两部分。对与大于
n
\sqrt n
n的,我们直接暴力,因为这样的串的个数不会超过
L
\sqrt L
L个,所以时间复杂度是
O
(
n
L
)
O(n\sqrt L)
O(nL)的。对与小于
n
\sqrt n
n的,我们提前预处理,时间复杂度
O
(
n
n
)
O(n\sqrt n)
O(nn)
所以时间复杂度是 O ( n n ) O(n\sqrt n) O(nn)的
c o d e code code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=2e5+10;
int n,m,a[N],v[510][N];
char s[N],t[N];
int main()
{
// freopen("similar.in","r",stdin);
// freopen("similar.out","w",stdout);
scanf("%s",s+1);n=strlen(s+1);
scanf("%d",&m);
for(int i=1;i<=n;i++)
a[i]=a[i-1]+s[i]-'0';
int T=sqrt(n);
for(int i=1;i<=T;i++)
for(int j=0;j<=n-i;j++)
v[i][a[j+i]-a[j]]++;
while(m--){
scanf("%s",t+1);int l=strlen(t+1),k=0;
for(int i=1;i<=l;i++)k+=(t[i]-'0');
if(l>T){
int ans=0;
for(int i=0;i<=n-l;i++)
ans+=((a[i+l]-a[i])==k);
printf("%d\n",ans);
}
else printf("%d\n",v[l][k]);
}
}