题目链接:http://poj.org/problem?id=3274
解法类型:hash
解题思路:一道hash题啊,找key啊。当时做的时候觉得hash不好用,但它就是可以用hash优化,参考了一下别人的算法,让我对hash有了更深的领悟。首先把数转化成二进制矩阵,然后用一个数组s[i][j]来储存第j列的前i个数二进制的和,再用一个数组c[i][j]=s[i][j]-s[i][0],这样,只要某两行c[i][j]相同,那么这两行就可以算成一个contiguous balanced group。key就出来了,求和再取余或相乘再取余,随你。。~
算法实现:
//STATUS:C++_AC_969MS_27536K
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int MAXN=100010,MAX_HASH=99991;
int s[MAXN][30],c[MAXN][30];
int count(int a,int b);
int k;
struct NODE //链表写hash表
{
struct NODE(){next=NULL;};
int num;
NODE *next;
}hash[MAX_HASH];
int main()
{
// freopen("in.txt","r",stdin);
int i,j,a,n,sumc,max;
while(~scanf("%d%d",&n,&k))
{
max=0;
memset(s,0,sizeof(s));
memset(hash,0,sizeof(hash));
NODE *p=(NODE*)malloc(sizeof(NODE));
hash[0].num=0,hash[0].next=p,p->next=NULL; //这个很重要,因为要考虑第一组的情况
for(i=1;i<=n;i++){
scanf("%d",&a);
for(j=0,sumc=0;j<k;j++){
s[i][j]=s[i-1][j]+((a&(1<<j))?1:0); //位运算二进制
c[i][j]=s[i][j]-s[i][0];
sumc+=c[i][j];
}
int t=sumc%MAX_HASH;
if(t<0)t=-t;
NODE *p=&hash[t];
for(;p->next!=NULL;p=p->next){ //搜索hash表
int ok=count(p->num,i);
if(ok!=-1 && ok>max)max=ok;
}
NODE *q=(NODE*)malloc(sizeof(NODE)); //搜索hash表
p->num=i;
p->next=q;
q->next=NULL;
}
printf("%d\n",max);
}
return 0;
}
int count(int a,int b) //比较是否构成contiguous balanced group
{
int j;
for(j=0;j<k;j++){
if(c[a][j]!=c[b][j])return -1;
}
return b-a;
}