Description
给出一个 01 01 串,问该串的恰有 k k 个的子串数量,两个子串只要在该串中位置不同则视为不同
Input
第一行一整数 k k ,之后输入一个串 s(1≤k,|s|≤106) s ( 1 ≤ k , | s | ≤ 10 6 )
Output
输出满足条件的子串数
Sample Input
1
1010
Sample Output
6
Solution
k=0 k = 0 时,统计该串连续 0 0 的个数即可,时,尺取,找到 k k 个后,假设右端点后面还有连续 R R 个,左端点后还有连续 L L 个,那么对答案的贡献即为 (L+1)⋅(R+1) ( L + 1 ) ⋅ ( R + 1 )
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=1000005;
int k,pos[maxn];
char s[maxn];
int main()
{
scanf("%d%s",&k,s+1);
int n=strlen(s+1);
ll ans=0;
if(k==0)
{
for(int i=1;i<=n;i++)
if(s[i]=='0')
{
int num=1;
while(i<n&&s[i]==s[i+1])i++,num++;
ans+=(ll)num*(num+1)/2;
}
}
else
{
int l=1,r=1,num=0;
while(l<=n)
{
while(num<k&&r<=n)
{
if(s[r]=='1')num++;
r++;
}
if(num<k)break;
//printf("l=%d r=%d\n",l,r);
int L=1;
while(l<=n&&s[l]=='0')l++,L++;
int R=1;
while(r<=n&&s[r]=='0')r++,R++;
//printf("L=%d R=%d\n",L,R);
ans+=(ll)L*R;
if(l>n||r>n)break;
l++,num--;
}
}
printf("%I64d\n",ans);
return 0;
}