题解: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)\)。
亲测可过,请勿抄袭!

浙公网安备 33010602011771号