Loading

题解:CF1045I Palindrome Pairs

题目链接:link

首先上思路:

如果一个字符串是回文串,只有当其中最多的只有一个字符的出现次数是奇数。

注意我们可以将每个字符串的字符出现次数的奇偶性用一个 \(26\) 位的二进制表示。

接下来就是是回文对的条件:

我们分为 \(2\) 种情况。

第一种情况:

两个字符串的二进制表示完全相同。那么也就是两个字符串的字符出现次数的奇偶性完全相同,所以拼接后的字符串中每个字符的出现次数都是偶数,所以它们可以构成回文串。

第二种情况:

两个字符串的二进制表示只有一位不相同。那么也就是拼接后的字符串也只有一个字符出现次数是奇数,所以它们也可以构成回文串。

最后就是统计回文串了!

我们可以使用哈希表 mp 用来记录每个二进制表示的出现次数。然后用 ct 来记录每个二进制表示可以匹配的次数。

那么最后的答案就是两种情况的和。

如果还不懂看看代码吧!

#include<bits/stdc++.h>
#define I using
#define AK namespace
#define IOI std
#define i_ak return
#define ioi  0
#define i_will signed
#define ak main
#define IMO ()
#define int long long
I AK IOI;
/*mp 记录每个二进制表示的出现次数,ct 记录每个二进制表示可以被匹配的次数*/ 
unordered_map<int,int>mp,ct;
vector<int>v;//存储所有二进制表示
/*n 表示字符串数量,x 表示当前字符串的二进制表示,res 代表结果*/ 
int n,x,res; 
i_will ak IMO{
	cin>>n;
	for(int e=1;e<=n;e++){
		x=0;
		string s;
		cin>>s;
		for(int i=0;i<s.size();i++)x^=(1<<(s[i]-'a'));//将字符串奇偶性记录到二进制表示中
		v.push_back(x);
		for(int i=0;i<26;i++)if(((x>>i)&1)==0)ct[(x+(1<<i))]++;//记录当前二进制表示仅有一位不同 
		mp[x]++;
	}
	for(auto e:mp)res+=e.second*(e.second-1)/2;
	for(auto t:v)res+=ct[t];
	cout<<res;
	i_ak ioi;
}

时间复杂度:\(O(N\times L)\),其中 \(L\) 是字符串的平均长度。

空间复杂度:\(O(N)\)

亲测可过,请勿抄袭!

posted @ 2025-06-09 15:45  盼满天繁星  阅读(8)  评论(0)    收藏  举报