Another Problem on Strings (codeforces)

Another Problem on Strings

问题:给出一个由 0 1 组成的字符串,问有k个1组成的字串有多少个。
例子:k = 2,字符串:01010。
有 101,0101,1010,01010;

先讲一个小技巧(刚不久前学的,没想到用上了)
计算 [某个子区间和为k]的区间 的个数,转化为计算 [区间和为k的区间] 是多少区间的子区间(有点抽象哈)
来个例子:[8, 1, 2, 1, 8],求子区间和为4的区间个数。
我们可以找到区间和为4的区间为[1, 2, 1],然后让这个区间(左边元素个数+1)*(区间右边元素个数+1)得到答案4。

回到上面的题目:我们呢只要找到每k个1的每个区间,对每个区间向左找 0 直到碰到 1,记下0的个数,同样的向右找,记下0的个数。
k等于0时,要求各个只有0的小区间的个数。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
char s[1000100];
ll ans[1000100];
int main() {
    
    
	ll n, len, u = 0, idx = 1, x = 1, y = 0, an = 0;
	scanf("%I64d", &n);
	scanf("%s", s);
	len = strlen(s);
	for(int i=0; s[i]; i++) {
    
    
		if(s[i] == '1') {
    
    
			ans[idx++] = i;//记录1的位置,方便计算。
			an += (y+1)*y/2; //加上每两个1之间组成的只有0的区间个数
			y = 0;
		} 
		if(s[i] == '0') y ++;//记录每两个1之间 0的个数
	}
	an += (y+1)*y/2; //把最后几个0组成的区间加上
	if(n == 0) {
    
    
		printf("%I64d", an);
		return 0;
	}
	for(int i=1; i+n<=idx; i++) {
    
    
	//x为左边找到的0的个数加1,y为右边找到的0的个数加1
		if(i == 1) x = ans[i] + 1;
		else x = ans[i]-ans[i-1];
		if(i + n == idx) y = (len-ans[i+n-1]);
		else y = ans[i+n]-ans[i+n-1];
		u += x*y;
	} 
	printf("%I64d", u);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45363113/article/details/106675157