Codeforces Round 855 (Div. 3),F

F. Dasha and Nightmares

思路:

  1. 首先,我们盯一下题目,发现符合要求的组合,25个字母,每个都是奇数个,那这个字符串显然也是奇数长度。ok,排除一个条件。
  2. 我们目的是字符串匹配,显然利用哈希是一种方便的方式。因为只有26个字母,所以32位的二进制足够我们表示所有情况。
    1. 我们可以开一个数组a,a[i]哪一位上有1,表示该位表示的字母存在。
    2. 因为,我们不需要知道一个字母一共出现多少次,只需要知道出现的奇偶次数即可。我们开个b数组,如果b[i]上哪一位为0,表示有偶数个该字母,为1,该字母出现奇数次(不开a,b同一个数组就是因为0是有这个字母还是没有会引发歧义)
  3. 我们如何进行i字符串与j字符串的哈希匹配呢?
    1. 前提是他们至少缺同一个字母。
    2. 剩下只需要剩下25个字母的数量异或都为1,就满足了条件。
#include <bits/stdc++.h>
using namespace std;
#define ll     long long
const int N = 2e5 + 10;

int a[N], b[N];
int mp[1 << 26];
int main()
{std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	string s;
	cin >> n;
	for (int i = 1; i <= n; ++i)
		{
			cin >> s;
			for (auto &c : s)
				{
					a[i] |= 1 << (c - 'a'); //或运算记录是否出现
					b[i] ^= 1 << (c - 'a'); //异或运算计算出现奇偶次数
				}
		}
	ll ans = 0;
	for (int c = 0; c < 26; ++c)
		{
			int tmp = (1 << 26) - 1 - (1 << c); //(1<<26)-1使得前25位都是1,-(1<<c)使得只有第c位不是1,用于后面异或匹配奇偶
			for (int i = 1; i <= n; ++i)
				{
					if (~(a[i] >> c) & 1) //如果第i串没有第c个字母
						{
							mp[b[i]]++;
							ans += mp[tmp ^ b[i]]; //tmp^b[i]就是与i串每个字母奇偶性匹配的哈希值
						}
				}
			//每次匹配的前提是缺少同一个字母c,所有缺少这个字母的匹配统计后,哈希匹配数要清空
			for (int i = 1; i <= n; ++i)if (~(a[i] >> c) & 1)mp[b[i]] = 0;
		}
	cout << ans << endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值