F. Dasha and Nightmares
Dasha, an excellent student, is studying at the best mathematical lyceum in the country. Recently, a mysterious stranger brought $n$ words consisting of small latin letters $s_1, s_2, \ldots, s_n$ to the lyceum. Since that day, Dasha has been tormented by nightmares.
Consider some pair of integers $\langle i, j \rangle$ ($1 \le i \le j \le n$). A nightmare is a string for which it is true:
- It is obtained by concatenation $s_{i}s_{j}$;
- Its length is odd;
- The number of different letters in it is exactly $25$;
- The number of occurrences of each letter that is in the word is odd.
For example, if $s_i=$ "abcdefg" and $s_j=$ "ijklmnopqrstuvwxyz", the pair $\langle i, j \rangle$ creates a nightmare.
Dasha will stop having nightmares if she counts their number. There are too many nightmares, so Dasha needs your help. Count the number of different nightmares.
Nightmares are called different if the corresponding pairs $\langle i, j \rangle$ are different. The pairs $\langle i_1, j_1 \rangle$ and $\langle i_2, j_2 \rangle$ are called different if $i_1 \neq i_2$ or $j_1 \neq j_2$.
Input
The first line contains a single integer $n$ ($1 \le n \le 2 \cdot 10^5$) — the number of words.
The following $n$ lines contain the words $s_1, s_2, \ldots, s_n$, consisting of small latin letters.
It is guaranteed that the total length of words does not exceed $5 \cdot 10^6$.
Output
Print a single integer — the number of different nightmares.
Example
input
10 ftl abcdefghijklmnopqrstuvwxy abcdeffghijkllmnopqrsttuvwxy ffftl aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyy thedevid bcdefghhiiiijklmnopqrsuwxyz gorillasilverback abcdefg ijklmnopqrstuvwxyz
output
5
Note
In the first test, nightmares are created by pairs $\langle 1, 3 \rangle$, $\langle 2, 5 \rangle$, $\langle 3, 4 \rangle$, $\langle 6, 7 \rangle$, $\langle 9, 10 \rangle$.
解题思路
枚举优化题,一般都会用到哈希表。
首先要发现一个隐藏的性质,就是如果拼接的字符串同时满足只有$25$个字母和每个字母出现奇数次这两个条件,那么这个拼接的字符串自然就满足长度为奇数的条件(因为奇数乘奇数等于奇数)。因此我们并不需要关注长度为奇数这个条件,而只关注剩下的那两个条件。
由于我们只关注每个字符串中出现了那些字母以及每个字符出现的奇偶性,而最多就只有$26$个字母,因此很自然想到用状态压缩,把$a \sim z$映射到$0 \sim 25$。对于第$i$个字符串$s_i$,定义$a_i$为$s_i$中出现的字母的状态,如果字母$c$出现过,那么$a_i$的第$c$位应该为$1$,否则为$0$。定义$b_i$为每个字母出现次数奇偶性的状态,如果字母$c$出现了奇数次,那么$b_i$的第$c$位应该为$1$,否则为$0$。
对于一个合法的拼接字符串$t$,很明显$t$的$a_t$所表示的状态中应该有$25$个$1$,$b_t$所表示的状态中应该也有$25$个$1$,且是$1$的位置都是一样的,即恰好有一个位为$0$且是同一个位,假设对应字母$c$。由于合法的拼接字符串状态少,因此我们就可以枚举$c$,一共有$26$个,来表示拼接的字符串中缺少了哪个字母,对应的$a_t = b_t = 2^{26} - 1 - 2^{c}$。然后对于每个$c$,枚举每一个字符串$i$,很明显$s_i$对应的$a_i$的第$c$位应该为$0$。然后看看$i$前面有多少个$j$,满足$a_j$的第$c$位为$0$,且有$b_j \oplus b_i = 2^{26} - 1 - 2^{c}$,即$b_j = b_i \oplus 2^{26} - 1 - 2^{c}$。因此可以开个哈希表来统计。
AC代码如下,时间复杂度为$O(\sum |s| + 26 \cdot n)$:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 2e5 + 10; 7 8 int a[N], b[N]; 9 int mp[1 << 26]; 10 11 int main() { 12 int n; 13 cin >> n; 14 for (int i = 0; i < n; i++) { 15 string s; 16 cin >> s; 17 for (auto &c : s) { 18 a[i] |= 1 << c - 'a'; 19 b[i] ^= 1 << c - 'a'; 20 } 21 } 22 LL ret = 0; 23 for (int c = 0; c < 26; c++) { 24 int st = (1 << 26) - 1 - (1 << c); 25 memset(mp, 0, sizeof(mp)); 26 for (int i = 0; i < n; i++) { 27 if (~(a[i] >> c) & 1) { 28 mp[b[i]]++; 29 ret += mp[st ^ b[i]]; 30 } 31 } 32 } 33 cout << ret; 34 35 return 0; 36 }
参考资料
Codeforces Round #855 (Div. 3) F:https://zhuanlan.zhihu.com/p/610978167
Codeforces Round 855 (Div. 3) Editorial:https://codeforces.com/blog/entry/113477
标签:nightmares,26,langle,字母,Nightmares,Dasha,rangle From: https://www.cnblogs.com/onlyblues/p/17178545.html