UVA_10391
我终于会用字符串的哈希函数之一了……
在这个哈希函数里面v&0x7FFFFFFF是为了保证v总是正的,这一点我们把16进制数写成2进制数就能很明显的看出来了,但这是v的范围仍然和int的正数范围一样大,为了节约存储空间我们可以最后让v模一个大素数,一般可以选1000003和10000019。
此外这个题目如果我们判断两个字符串合成的新字符串是否出现过,这样复杂度会比较高(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;
}