la 2965 Jurassic Remains (中途相遇法)

把串分成前后两半,前面的做暴力枚举,并把结果丢到集合里去,

后面的也暴力枚举,并且每次的结果去集合里看有无出现过相同的.

如果有那么异或后为0,就是符合题目要求的,选出包含字符串个数最多的!

这样一优化,前后两个2^12+2^12,瞬间时间复杂度开方了!

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
typedef long long ll;
using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=1e6+10;

int n;
int a[25];

map<int,int>table;

int bitcount(int x){
	return x==0 ? 0 : (bitcount(x/2)+(x&1)) ;
}


int main()
{
	while(scanf("%d",&n)!=EOF && n){
		char s[1005];
		for(int i=0;i<n;++i){
			scanf("%s",&s);
			//printf("%s
", s);
			a[i]=0;
			for(int j=0 ; s[j]!='' ;++j ){
				a[i]^=( 1<<( s[j]-'A' ) );
			}
		}

		int n1=n/2;
		int n2=n-n1;
		table.clear();
		for(int i=0;i< (1<<n1) ;++i ){
			int x=0;
			for(int j=0;j<n1;++j){
				if(i & (1<<j)){
					x^=a[j];
				}
			}
			if(!table.count(x) || bitcount(table[x])<bitcount(i))table[x]=i;
		}
		int ans=0;
		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];
				}
			}
			if( table.count(x) && bitcount(ans)< bitcount(table[x])+bitcount(i) ){
				ans=(i<<n1)^table[x];
			}
		}

		printf("%d
",bitcount(ans) );
		for(int i=0;i<n;++i)
			if( ans&(1<<i) )
				printf("%d ",i+1 );
		printf("
");
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/bruce27/p/4787017.html