您的位置:首页 > 编程语言 > Go语言

Gold Balanced Lineup(哈希表)

2013-08-15 20:20 211 查看
TimeLimit:2000MSMemoryLimit:65536K
TotalSubmissions:10711Accepted:3182
Description

FarmerJohn'sNcows(1≤N≤100,000)sharemanysimilarities.Infact,FJhasbeenabletonarrowdownthelistoffeaturessharedbyhiscowstoalistofonlyKdifferentfeatures(1≤K≤30).Forexample,cowsexhibitingfeature#1mighthavespots,cowsexhibitingfeature#2mightpreferCtoPascal,andsoon.

FJhasevendevisedaconcisewaytodescribeeachcowintermsofits"featureID",asingleK-bitintegerwhosebinaryrepresentationtellsusthesetoffeaturesexhibitedbythecow.Asanexample,supposeacowhasfeatureID=13.Since13writteninbinaryis1101,thismeansourcowexhibitsfeatures1,3,and4(readingrighttoleft),butnotfeature2.Moregenerally,wefinda1inthe2^(i-1)placeifacowexhibitsfeaturei.

Alwaysthesensitivefellow,FJlinedupcows1..Ninalongrowandnoticedthatcertainrangesofcowsaresomewhat"balanced"intermsofthefeaturestheexhibit.Acontiguousrangeofcowsi..jisbalancedifeachoftheKpossiblefeaturesisexhibitedbythesamenumberofcowsintherange.FJiscuriousastothesizeofthelargestbalancedrangeofcows.Seeifyoucandetermineit.

Input

Line1:Twospace-separatedintegers,NandK.
Lines2..N+1:Linei+1containsasingleK-bitintegerspecifyingthefeaturespresentincowi.Theleast-significantbitofthisintegeris1ifthecowexhibitsfeature#1,andthemost-significantbitis1ifthecowexhibitsfeature#K.
Output

Line1:Asingleintegergivingthesizeofthelargestcontiguousbalancedgroupofcows.
SampleInput

73
7
6
7
2
1
4
2

SampleOutput

4

题意:有n个二进制长度为k的特征数(十进制),求最大的连续的牛的数目,使这些牛每个特征的总数相等;

思路:

先把7个十进制特征数转换为二进制,并逆序存放到特征数组feature[][],得到:

7à111

6à011

7à111

2à010

1à100

4à001

2à010

(行数为cow编号,自上而下从1开始;列数为特征编号,自左到右从0开始)

再求sum数组,逐行累加得,sum数组为

111

122

233

243

343

344

354

再利用C[i][y]=sum[i][y]-sum[i][0]求C数组,即所有列都减去第一列

注意C数组有第0行,为全0

000à第0行

000

011

011

021

010

011

021

显然第2行与第6行相等,均为011,且距离最远,距离为6-2=4,这就是所求。

但是最大数据有10W个,即10W行,因此不能直接枚举找最大距离,必须用Hash查找相同行,找到相同行再比较最大距离。

注意C数组的值可能为负数,因此生成key值时要注意保证key为非负数。

#include<stdio.h>
#include<string.h>
#include<algorithm>
usingnamespacestd;

constintprime=99991;
structnode
{
intid;
structnode*next;
}*hash[prime];//邻接表

intsum[100100][32];//从第一头牛到第i头牛,特征j总共出现了sum[i][j]次;
intc[100100][32];//c[i][j]=sum[i][j]-sum[i][0];
intn,k,maxlen;

boolcheck(intx,inty)
{
inti;
for(i=0;i<k;i++)
if(c[x][i]!=c[y][i])
returnfalse;
returntrue;
}

voidHash(intci)//ci代表序列的下标
{
intkey=0,i;
//生成关键字
for(i=1;i<k;i++)
key+=c[ci][i]*i;//key有可能是负值,要取绝对值,对大素数取余;
key=abs(key)%prime;
if(!hash[key])//出现新的key;
{
hash[key]=newstructnode;
hash[key]->id=ci;
hash[key]->next=NULL;
}
//当key发生冲突时
else
{
structnode*p=hash[key];
if(check(p->id,ci))
{
intdis=ci-(p->id);
if(dis>maxlen)
maxlen=dis;//因p->id是从小到大的,所以当遍历有p->id满足时肯定是当前最优的,
return;//可以return;

}
else
{
while(p->next)
{
if(check(p->next->id,ci))
{
intdis=ci-(p->next->id);
if(dis>maxlen)
maxlen=dis;
return;

}
p=p->next;
}
//当ci序列与其它序列都不相同时就插到该链的最后;
structnode*tmp=newstructnode;
tmp->id=ci;
tmp->next=NULL;
p->next=tmp;
}
}
return;
}
intmain()
{
inti,j;
while(~scanf("%d%d",&n,&k))
{
for(i=0;i<k;i++)
{
sum[0][i]=0;
c[0][i]=0;//第0头牛初始化
}
memset(hash,0,sizeof(hash));
Hash(0);//把第0头牛放入哈希表
maxlen=0;
for(i=1;i<=n;i++)
{
intx;
scanf("%d",&x);
for(j=0;j<k;j++)
{
sum[i][j]=sum[i-1][j]+x%2;
c[i][j]=sum[i][j]-sum[i][0];
x=x/2;
}
Hash(i);
}
printf("%d\n",maxlen);
}
return0;
}


ViewCode


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: