题目意思就是给出一堆字符串求出一个字符串集合,满足里面的每个字符的出现次数都是偶数,并且字符串的数量最多.
一看到题目首先想到的就是枚举2^24个状态,结果不用试都肯定是超时的.
然后看了解题报告,刘汝佳神牛的书上用的是二进制枚举子集加二进制存储状态来做的.
首先保存每个字符串的xor结果(同一个字符串里面的字符也是可以配对的).
然后首先枚举前n / 2个字符串子集,将各个子集的字符串xor值用map存起来.
然后再枚举后n - n / 2个字符串的子集,判断各个子集的xor值是否存在map中(也就是偶数,配对上了),维护字符串数量最多的子集.
总的复杂就是2^(n/2) * logn
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const int maxn = 25;
map<int,int>tb;
int A[maxn];
char s[1000];
int n;
int bitcount(int x){
int ret = 0;
while(x){
if(x & 1)ret++;
x >>= 1;
}
return ret;
}
int main(){
while(~scanf("%d", &n)){
tb.clear();
for(int i = 0; i < n; ++i){
scanf("%s", s);
A[i] = 0;
for(int j = 0; s[j]; ++j){
A[i] ^= (1 << (s[j] - 'A'));
}
}
int n1 = n / 2, n2 = n - n1, ans = 0;
for(int i = 0; i < (1 << n1); ++i){//枚举前n / 2个字符串的xor值所对应的子集
int x = 0;//子集对应的xor值
for(int j = 0; j < n1; ++j){
if(i & (1 << j)){//子集中有这个字符串
x ^= A[j];//xor
}
}
if(!tb.count(x) || bitcount(tb[x]) < bitcount(i)){//x尚不存在对应的子集或者当前枚举的子集中的字符串数量比x对应的子集的字符串多
tb[x] = i;//更新xor值对应的子集
}
}
for(int i = 0; i < (1 << n2); ++i){//枚举后半部分字符串
int x = 0;
for(int j = 0; j < n2; ++j){
if(i & (1 << j)){//子集中有这个字符串
x ^= A[n1 + j];//xor
}
}
if(tb.count(x) && bitcount(ans) < bitcount((i << n1) ^ tb[x])){//当前子集的值存在于前n / 2个子集中(配对上了)
ans = (i << n1) ^ tb[x];//更新最大子集(i << n1 因为是后半部分)
}
}
printf("%d\n", bitcount(ans));
for(int i = 0; i < n; ++i){
if(ans & (1 << i)){//最大子集中存在这个字符串
printf("%d ", i + 1);
}
}
printf("\n");
}
return 0;
}