C. Vus the Cossack and Strings
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).
For example, let b=00110b=00110, and c=11000c=11000. In these strings, the first, second, third and fourth positions are different.
Vus the Cossack counts the number of such substrings cc such that f(b,c)f(b,c) is even.
For example, let a=01100010a=01100010 and b=00110b=00110. aa has four substrings of the length |b||b|: 0110001100, 1100011000, 1000110001, 0001000010.
- 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.
Vus can not find the answer for big strings. That is why he is asking you to help him.
The first line contains a binary string aa (1≤|a|≤1061≤|a|≤106) — the first string.
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)的時間復雜度就可以完成運算。
一個從很久以前就開始做的夢。
