//题意:求解最大的连续区间使得该区间中每种特征出现的次数是相等的
//可以用树状数组类似方法求解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;
}
poj3274数位HASH
最新推荐文章于 2019-07-22 16:47:42 发布