CodeForces 165C Another Problem on Strings

A string is binary, if it consists only of characters "0" and "1".

String v is a substring of string w if it has a non-zero length and can be read starting from some position in string w. For example, string "010" has six substrings: "0", "1", "0", "01", "10", "010". Two substrings are considered different if their positions of occurrence are different. So, if some string occurs multiple times, we should consider it the number of times it occurs.

You are given a binary string s. Your task is to find the number of its substrings, containing exactly k characters "1".

Input

The first line contains the single integer k (0 ≤ k ≤ 106). The second line contains a non-empty binary string s. The length of s does not exceed 106 characters.

Output

Print the single number — the number of substrings of the given string, containing exactly k characters "1".

Please do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cincout streams or the %I64d specifier.

Example
Input
1
1010
Output
6
Input
2
01010
Output
4
Input
100
01010
Output
0
Note

In the first sample the sought substrings are: "1", "1", "10", "01", "10", "010".

In the second sample the sought substrings are: "101", "0101", "1010", "01010".


題意很清楚,給一個字符串s,和一個數字k,詢問有多少個子串滿足1的數目等於k。

1:先特殊考慮k=0這種情況,當k=0時,我們只需要考慮連續0的個數。比如連續的0的個數爲ans,那麼此時有ans*(ans+1)/2個子串滿足。所以我們只需要遍歷一下字符串,每次求一段連續的0,然後計數就可以了。

2: 然後再考慮k>0這種情況,當k>0時,我們需要記錄每個'1'字符左右的'0'字符的個數。比如k=1,s="0100",那麼字符'1'的左右分別有1和2個'0'字符,滿足要求的子串爲'01' , '1' , '010' , '10' , '0100' , '100',個數爲6,所以可以得出結果爲左右字符'0'的個數加上1相乘即可,爲了方便,我們計數的時候初始化爲1,所以直接用l*r即可(l代表左邊字符'0'的個數,r代表右邊字符'0'的個數)。

需要注意的一點是題目是數據範圍很大,我除了k之外,其他的都用了long long ,不然會莫名的wa。具體請看代碼:

#include <stdio.h>
#include <string.h>
#define ll long long
char c[1000006];
struct node{ //存字符1的左右字符0的個數 
	ll l, r;
}s[1000006];
int main() {
	int k;
	while(~scanf("%d", &k)) {
		scanf("%s", c);
		ll m = strlen(c);
		ll t = 0, ans = 1;//t代表字符1的個數 , ans用於計數0 
		ll sum1 = 0, sum2 = 0;//sum1用於計算當k>0時的結果,sum2用於計算k=0的結果 
		for(int i = 0; i < m; i++) {
			if(c[i] == '0') ans++; //計數 
			else {
				sum2 += (ans*(ans-1))/2;//因爲ans初始爲1,所以是ans*(ans-1)/2 
				if(t == 0) {            //當t=0的時候記錄左邊的值ans
					s[t++].l = ans;
				}
				else {
					s[t-1].r = ans;     //記錄上一個字符1的右邊字符0的個數 
					s[t++].l = ans;     //記錄此時字符1左邊0的個數,這兩步要弄懂
				}                       //兩個1字符中間的字符0的個數需要格外注意 
				ans = 1;                //重新開始找
			}
			if(i == m-1) {              //當找到最後的時候需要格外考慮一下 
				sum2 += (ans*(ans-1))/2;
				s[t-1].r = ans;
			}
		}
		if(k == 0) {               //當k=0的時候 
			printf("%lld\n", sum2);
			continue;
		}
		ll l = 0;
		ll r = l+k-1;
		while(r < t) {
			sum1 += s[l].l*s[r].r;
			l++;r++;
		}
		printf("%lld\n", sum1);
	}
	return 0;
}

發佈了221 篇原創文章 · 獲贊 11 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章