继续hash,这题我自己也AC了,不过当时没用hash,先说一下我自己的思路。然后再贴大神的hash。
这题显然是求交集的问题。
我首先把第一个集合作为当前的交集。然后每进来一组集合,就和当前交集求一次交集。自己实现了一个求交集的函数,就是排序后,用两个游标非别指两个集合,遇到一样的就取出存到另一个集合中去。最后在把这个集合赋值给当前集合。
显然还有一个去重的问题。在输出的时候,遇到一样的就不输出。
贴代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a<b;
}
int ans[1001]={-1};
int intersection(int tmp[],int m1,int ans[],int m2)
{
int point1=0,point2=0,i=0,j,c[1001]={-1};
if(tmp==NULL||ans==NULL||m1==0||m2==0)
return -1;
else
{
while(point1<m1&&point2<m2)
{
if(tmp[point1]>ans[point2])
{
point2++;
}
else if(tmp[point1]==ans[point2])
{
c[i++]=tmp[point1];
point1++;
point2++;
}
else
point1++;
}
}
if(i==0)return -1;
else
{
for(j=0;j<i;j++)
ans[j]=c[j];
return i;
}
}
int main()
{
int n,m1,m2,i,j,count,t=0;
int tmp[1001]={-1};
scanf("%d",&n);
scanf("%d",&m2);
for(i=0;i<m2;i++)
{
scanf("%d",&ans[i]);
}
sort(ans,ans+m2,cmp);
for(i=0;i<n-1;i++)
{
scanf("%d",&m1);
for(j=0;j<m1;j++)
{
scanf("%d",&tmp[j]);
}
sort(tmp,tmp+m1,cmp);
count=intersection(tmp,m1,ans,m2);
m2=count;
if(count==-1)
{
break;
}
}
if(i>=n-1||n==1)
{
for(j=1;j<m2;j++)
{
if(ans[j]==ans[j-1])continue;
else
t++;
}
printf("%d\n%d",t+1,ans[0]);
for(j=1;j<m2;j++)
{
if(ans[j]==ans[j-1])continue;
else
printf(" %d",ans[j]);
}
printf("\n");
}
else
printf("0\n");
return 0;
}
/*
4
2 2 4
2 2 4
3 2 2 4
4 2 3 4 5
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#define LL __int64
#define N 100003
#define MOD 100003//模值
using namespace std;
int cnt[N],has[N];//cnt用于计数,计每个元素是否在每个集合都出现过
bool vis[N];
int ans[1007];
inline int hash(int x){
int y=(x%MOD+MOD)%MOD;
while(vis[y]&&has[y]!=x)//解决冲突,采用线性重新散列技术
y=(y+1)%MOD;
return y;
}
int main(){
int n,m;
scanf("%d",&n);
memset(cnt,0,sizeof(cnt));
memset(vis,false,sizeof(vis));
int x,y;
for(int i=1;i<=n;i++){
scanf("%d",&m);
for(int j=0;j<m;j++){
scanf("%d",&x);
y=hash(x);
if(cnt[y]==i-1){//这里本来在疑惑重复的问题,后来发现,是与i相关而不是j
cnt[y]++;
has[y]=x;
vis[y]=true;
}
}
}
int tot=0;
for(int k=0;k<MOD;k++){
if(cnt[k]==n)
ans[tot++]=has[k];
}
sort(ans,ans+tot);
printf("%d\n",tot);
for(int r=0;r<tot;r++){//这个末尾无空格的方式和我以往用的不同,学习
printf("%d",ans[r]);
if(r==tot-1)
printf("\n");
else
printf(" ");
}
return 0;
}