UVA_10391

我终于会用字符串的哈希函数之一了……

在这个哈希函数里面v&0x7FFFFFFF是为了保证v总是正的,这一点我们把16进制数写成2进制数就能很明显的看出来了,但这是v的范围仍然和int的正数范围一样大,为了节约存储空间我们可以最后让v模一个大素数,一般可以选100000310000019

此外这个题目如果我们判断两个字符串合成的新字符串是否出现过,这样复杂度会比较高(n^2),我们不如去判断一个字符串拆成的两半是否都出现过,这样复杂度是n*m,其中m约是字符串的平均长度。

#include<stdio.h>
#include
<string.h>
#include
<stdlib.h>
char st[121000][30],temp[30];
int head[10000019],next[121000];
char res[121000][30];
int r[121000];
int cmp(const void *_p,const void *_q)
{
int *p=(int *)_p;
int *q=(int *)_q;
return strcmp(res[*p],res[*q]);
}
int hash(char *str)
{
int seed=31,v=0;
while(*str)
{
v
=v*seed+*(str++);
}
return (v&0x7FFFFFFF)%10000019;
}
void insert(int s)
{
int h;
h
=hash(st[s]);
next[s]
=head[h];
head[h]
=s;
}
int search(char *str)
{
int i,h;
h
=hash(str);
for(i=head[h];i!=-1;i=next[i])
if(strcmp(str,st[i])==0)
break;
if(i==-1)
return 0;
else
return 1;
}
int main()
{
int i,j,k,n,ans;
char t;
n
=0;
memset(head,
-1,sizeof(head));
while(gets(st[n])!=NULL)
{
insert(n);
n
++;
}
ans
=0;
for(i=0;i<n;i++)
{
k
=strlen(st[i]);
if(k<2)
continue;
strcpy(temp,st[i]);
for(j=1;j<k;j++)
{
t
=temp[j];
temp[j]
='\0';
if(search(temp)&&search(&st[i][j]))
{
strcpy(res[ans
++],st[i]);
break;
}
temp[j]
=t;
}
}
for(i=0;i<ans;i++)
r[i]
=i;
qsort(r,ans,
sizeof(r[0]),cmp);
for(i=0;i<ans;i++)
printf(
"%s\n",res[r[i]]);
return 0;
}

  

posted on 2011-09-18 00:15  Staginner  阅读(587)  评论(0编辑  收藏  举报