C. Vus the Cossack and Stringsc++
Vus the Cossack has two binary strings, that is, strings that consist only of "0" and "1". We call these strings aa and bb. It is known that |b|≤|a||b|≤|a|, that is, the length of bb is at most the length of aa.数组
The Cossack considers every substring of length |b||b| in string aa. Let's call this substring cc. He matches the corresponding characters in bband cc, after which he counts the number of positions where the two strings are different. We call this function f(b,c)f(b,c).ide
For example, let b=00110b=00110, and c=11000c=11000. In these strings, the first, second, third and fourth positions are different.this
Vus the Cossack counts the number of such substrings cc such that f(b,c)f(b,c) is even.spa
For example, let a=01100010a=01100010 and b=00110b=00110. aa has four substrings of the length |b||b|: 0110001100, 1100011000, 1000110001, 0001000010.code
- f(00110,01100)=2f(00110,01100)=2;
- f(00110,11000)=4f(00110,11000)=4;
- f(00110,10001)=4f(00110,10001)=4;
- f(00110,00010)=1f(00110,00010)=1.
Since in three substrings, f(b,c)f(b,c) is even, the answer is 33.blog
Vus can not find the answer for big strings. That is why he is asking you to help him.three
The first line contains a binary string aa (1≤|a|≤1061≤|a|≤106) — the first string.ci
The second line contains a binary string bb (1≤|b|≤|a|1≤|b|≤|a|) — the second string.字符串
Print one number — the answer.
01100010 00110
3
1010111110 0110
4
The first example is explained in the legend.
In the second example, there are five substrings that satisfy us: 10101010, 01010101, 11111111, 11111111.
题意:题目给了一个较长字符串a以及一个较短字符串b,在a中取与b长度相等的子串,比较子串与b字符串中有几组字符不同。
当天下午因为在探讨研究这场CF B题的4 4 状况,而致使后来没怎么看这道题,但实际上这道题对于位运算的运用是十分的基础并且有效的。
顺带一提,B题4 4的状况,不只hack掉了基本全部的AC代码,甚至让这场比赛都不算rate了
先科普一下 位运算中的 异或(运算符"^"),在二进制中,若是两个数字相同的话,那么异或的结果就是0,不然就是1;同时两次异或同一个数字,就至关于没有没有异或过这个数字
先贴一下代码


1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int inf = 0x3f3f3f3f; 5 const int maxn = 2000030; 6 char a[maxn],b[maxn]; 7 int ans = 0,sum = 0; 8 int main(){ 9 scanf("%s",a); 10 scanf("%s",b); 11 int len_a = strlen(a); 12 int len_b = strlen(b); 13 for(int i = 0 ; i < len_b ; i++){ 14 ans=ans^a[i]^b[i]; 15 } 16 if(ans%2 == 0) sum++; 17 for(int i = len_b ; i < len_a ; i++){ 18 ans = ans^a[i-len_b]^a[i]; 19 if(ans % 2 == 0) sum++; 20 } 21 printf("%d\n",sum); 22 return 0; 23 }
例如,样例一:
一开始先对于 i = 0 到 i = strlen(b) 中 b 字符串和a的子串进行异或操做,若是异或结果(ans)能够整除2,那么就表明这个子串对于b而言有偶数组不一样。
以后就能够有i = len 向 i = strlen(a)中逐位挪移,而计算结果就是 新的 ans = 旧的 ans ^ a[i - len] ^ a[i])。^a[i - len]就是消除a[i - len]的影响,^a[i]就是将a[i]的影响加入计算
一开始的状态
(0^0)^(1^0)^(1^1)^(0^1)^(0^0)
向右挪移一位
(0^0)^(1^0)^(1^1)^(0^1)^(0^0)^0^0 // 第一个0 是a[i - len],第二个0是a[i];
= 0^(0^0)^(1^0)^(1^1)^(0^1)^(0^0)^0 // 由于一个数字异或两次至关于没有异或
= ·(0^1)^(0^1)^(1^0)^(1^0)^(0^0)
这样只须要O(n)的时间复杂度就能够完成运算。
一个从好久之前就开始作的梦。