poj3274数位HASH

//题意:求解最大的连续区间使得该区间中每种特征出现的次数是相等的
//可以用树状数组类似方法求解sum[i][]表示0-i所有属性出现的次数
//那么就是求sum[j][] - sum[i][]最大的j-i的值
//sum[j][k]-sum[i][k] = sum[j][0]- sum[i][0]  sum[j][k] - sum[j][0] = sun[i][k] - sum[i][0]

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

#define  MAXN  100010
static int n;
static int nsum[MAXN][31];
static int C[MAXN][31];
static int K;
static const int mod=99991;

static int maxans;
typedef struct HashNode
{
	int data[31];
	int num;
	HashNode* next;
	HashNode()
	{
		next = 0;
	}
}*HashTable;
HashTable xHash[mod];

static int getHash(int num)
{
	int key = 0;
	//与位置有关的话
	for (int i=0;i<K;++i)
	{
		key+= C[num][i]*i;
	}
	key>0?key:key = -key;
	key%=mod;
	return key;
}
static void initHash()
{
	memset(xHash,0,sizeof(xHash));
}

static bool kmpd(HashTable a,int*d)
{
	for (int i=0;i<K;++i)
	{
		if (a->data[i]!=d[i])
		 return false;
	}
	return true;
}
static void insertHash(int num)
{
	int key = getHash(num);
	if (xHash[key]==0)
	{
		xHash[key] = new HashNode();
		for (int i=0;i<K;++i)
		 xHash[key]->data[i] = C[num][i];
		xHash[key]->next = 0;
		xHash[key]->num = num;
		return;
	}
	else
	{
		HashTable head = xHash[key];
		for (head;head!=0;head = head->next)
		{
			if (kmpd(head,C[num])){
			    int dif = num - head->num;
				if (dif>maxans)
				 maxans = dif;
				return;
			}
		}
		head = xHash[key];
		HashTable tmp = new HashNode();
		for (int i=0;i<K;++i)
			tmp->data[i] = C[num][i];
		tmp->num = num;
		tmp->next = head;
		xHash[key] = tmp;
	}
}
static int xpow(int a,int s)
{
	if (s==0)
	 return 1;
	int t = xpow(a*a,s/2);
	if (s&1)
	 t*=a;
	return t;
}


int main()
{

	scanf("%d %d",&n,&K);
	int p;
	memset(nsum,0,sizeof(nsum));
	memset(C,0,sizeof(C));
	for (int i=1;i<=n;++i)
	{
		scanf("%d",&p);
		if (p==xpow(2,K)-1)
		 maxans = 1;
		for (int j=0;j<K;++j){
			if (i==0)
			{
				if ((1<<j)&p)nsum[i][j]++;
			}
			else
			{
				nsum[i][j] = nsum[i-1][j];
				if ((1<<j)&p)
					nsum[i][j]++;
			}
			C[i][j] = nsum[i][j];
		}
		for (int j=0;j<K;++j)
		    C[i][j]-=nsum[i][0];
	}
	initHash();
	insertHash(0);
	for (int i=1;i<=n;++i)
		insertHash(i);
	printf("%d\n",maxans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值