POJ---3274[Gold Balanced Lineup] 数组的hash

 

 

hash函数抄网上的,自己写的死活没过:

 

 

/*数组的hash*/
//思路:
//(1):sum[i][j]表示前i头牛第j个特征的总和
//(2):sum[b][j]-sum[a-1][j];表示[a,b]头牛第j个特征总和
//(3):sum[b][1]-sum[a-1][1]=....=sum[b][K]-sum[a-1][K];表示[a,b]这(b-a+1)头牛是平衡的
//(4):转换成:
//sum[b][1]-sum[b][2]=sum[a][1]-sum[a][1];
//sum[b][1]-sum[b][3]=sum[a][1]-sum[a][3];
//.......................................
//.......................................
//sum[b][1]-sum[b][K-1]=sum[a][1]-sum[a][K-1];
//sum[b][1]-sum[b][K]=sum[a][1]-sum[a][K];
//(5):令c[i][j]=sum[i][1]-sum[i][j];
//(6):则表示[a,b]这(b-a+1)头牛是平衡的可转换成判断c[a-1]=c[b]是否成立
//(7):这样我们就可以在求的c[i][j](1<=i<=N,1<=j<=K)的基础上,对数组c[i](1<=i<=N)hash,用开散列法(拉链法)求解即可.

 

CODE:

/*AC代码:235ms*/
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#define max(a,b) (a>b?a:b)
#define MOD 19997
#define MAXN 100005
using namespace std;
int head[20000],next[MAXN];
int N,K;
int sum[MAXN][33],c[MAXN][33];
int hash(int v[])//hash函数
{
	int i,h=0;
	for(i=1;i<=K;i++)
		h=((h<<2)+(v[i]>>4))^(v[i]<<10);
	h%=MOD;
	h=h<0?h+MOD:h;
	return h;
}
void Init()
{
	int i,j,temp;
	memset(sum,0,sizeof(sum));
	for(i=1;i<=N;i++)
	{
		scanf("%d",&temp);
		for(j=1;j<=K;j++)
		{
			sum[i][j]=sum[i-1][j]+temp%2;
			temp/=2;
		}
		for(j=1;j<=K;j++)
			c[i][j]=sum[i][1]-sum[i][j];
	}
}
void Solve()
{
	int i,j,k,ans=0;
	memset(head,-1,sizeof(head));
	for(i=0;i<=N;i++)//注意这里从0开始
	{
		int h=hash(c[i]);
		//if(i==0)
		// printf("*%d %d\n",i,h);
		bool ok=false;
		for(j=head[h];j!=-1;j=next[j])
		{
			for(k=1;k<=K;k++)
			{if(c[i][k]!=c[j][k]) break;}
			if(k>K)//find,因为每个都不同,所以不必再往下找了
			{
				ans=max(ans,i-j);//注意不能加一
				ok=true;
				break;
			}
		}
		if(!ok)//已经有相同的就不用再插入了
		{
			next[i]=head[h];
			head[h]=i;
		}
	}
	printf("%d\n",ans);
}
int main()
{
	while(scanf("%d%d",&N,&K)!=EOF)
	{
		Init();
		Solve();
	}
	return 0;
}

 

你可能感兴趣的:(c)