F. Dasha and Nightmares

文章描述了一个关于Dasha的数学问题,她在研究由小写字母组成的字符串。目标是找出满足特定条件(长度奇数,25种不同字母且每种出现一次)的字符串对的数量。解题策略涉及枚举优化和使用哈希表进行状态压缩。给出的AC代码实现了这个问题的解决方案,时间复杂度为O(∑|s|+26⋅n)。
摘要由CSDN通过智能技术生成

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 s1,s2,…,sn to the lyceum. Since that day, Dasha has been tormented by nightmares.

Consider some pair of integers ⟨i,j⟩ (1≤i≤j≤n). A nightmare is a string for which it is true:

It is obtained by concatenation sisj;
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 si= "abcdefg" and sj= "ijklmnopqrstuvwxyz", the pair ⟨i,j⟩ 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 ⟨i,j⟩ are different. The pairs ⟨i1,j1⟩ and ⟨i2,j2⟩ are called different if i1≠i2 or j1≠j2.

Input
The first line contains a single integer n (1≤n≤2⋅105) — the number of words.

The following n lines contain the words s1,s2,…,sn, consisting of small latin letters.

It is guaranteed that the total length of words does not exceed 5⋅106.

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 ⟨1,3⟩, ⟨2,5⟩, ⟨3,4⟩, ⟨6,7⟩, ⟨9,10⟩.

解题思路
  枚举优化题,一般都会用到哈希表。

  首先要发现一个隐藏的性质,就是如果拼接的字符串同时满足只有25个字母和每个字母出现奇数次这两个条件,那么这个拼接的字符串自然就满足长度为奇数的条件(因为奇数乘奇数等于奇数)。因此我们并不需要关注长度为奇数这个条件,而只关注剩下的那两个条件。

  由于我们只关注每个字符串中出现了那些字母以及每个字符出现的奇偶性,而最多就只有26个字母,因此很自然想到用状态压缩,把a∼z映射到0∼25。对于第i个字符串si,定义ai为si中出现的字母的状态,如果字母c出现过,那么ai的第c位应该为1,否则为0。定义bi为每个字母出现次数奇偶性的状态,如果字母c出现了奇数次,那么bi的第c位应该为1,否则为0。

  对于一个合法的拼接字符串t,很明显t的at所表示的状态中应该有25个1,bt所表示的状态中应该也有25个1,且是1的位置都是一样的,即恰好有一个位为0且是同一个位,假设对应字母c。由于合法的拼接字符串状态少,因此我们就可以枚举c,一共有26个,来表示拼接的字符串中缺少了哪个字母,对应的at=bt=226−1−2c。然后对于每个c,枚举每一个字符串i,很明显si对应的ai的第c位应该为0。然后看看i前面有多少个j,满足aj的第c位为0,且有bj⊕bi=226−1−2c,即bj=bi⊕226−1−2c。因此可以开个哈希表来统计。

  AC代码如下,时间复杂度为O(∑|s|+26⋅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 }

复制代码
本文章来源于网络,版权归原作者所有,如果地推平台本站文章侵犯了您的权益,请联系我们删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dituirenwu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值