哈希
题意简短:单case,输入一列单词即一个字典,已经按字典序排好输入,上限为120000,然后要你找一些单词,这种单词可以分为两部分,两部分都是字典里面的单词,按字典序输出这种单词
很裸的哈希,对于每个单词,将其分成两部分,一共有len中分法,然后去查找是否都在字典中,如果都在字典中就输出(因为输入已经按字典序排好,扫描时直接扫下来就可以了,找到合适的就输出)
问题的关键就转变为,给你一个单词,怎么判断这个单词是不是在字典中,用哈希就可以快速判断到。输入时随便将每个单词都用哈希函数映射掉,每得到要查询的单词也直接映射过去查找
处理冲突的方法是链表(静态链表数组模拟)
用了BKDHash函数在处理字符串的映射
BKDHash,40ms
#include <cstdio>
#include <cstring>
#define N 120000
#define LEN 110
#define P 0x7fffffff
int n,tot;
char word[N+10][LEN];
int head[N+10];
struct list
{
int n;
int next;
}e[N+10];
void add(unsigned int index ,int m)
{
e[tot].n = m;
e[tot].next = head[index];
head[index] = tot++;
}
unsigned int BKDHash(char *str)
{
unsigned int seed = 131;
unsigned int hash = 0;
int len = strlen(str);
for(int i=0; i<len; i++)
hash = hash * seed + str[i];
return (hash & P) % N;
}
int find(char *str)
{
unsigned int index = BKDHash(str);
for(int k=head[index]; k!=-1; k=e[k].next)
{
int m = e[k].n;
if(!strcmp(word[m] , str))
return k;
}
return -1;
}
int main()
{
n = tot = 0;
memset(head,-1,sizeof(head));
while(scanf("%s",word[n])!=EOF)
{
unsigned int index = BKDHash(word[n]);
add(index , n);
n++;
}
for(int i=0; i<n; i++)
{
char str1[LEN] , str2[LEN];
int len = strlen(word[i]);
for(int j=0; j<len-1; j++)
{
int k,kk;
for(k=0,kk=0; kk<=j; k++,kk++)
str1[k] = word[i][kk];
str1[k] = '\0';
for(k=0,kk=j+1; kk<len; k++,kk++)
str2[k] = word[i][kk];
str2[k] = '\0';
int ok[2];
ok[0] = find(str1);
ok[1] = find(str2);
if(ok[0] != -1 && ok[1] != -1)
{
printf("%s\n",word[i]);
break;
}
}
}
return 0;
}
自己瞎比比写的一个字符串哈希,冲突死了,200ms
#include <cstdio>
#include <cstring>
#define N 120000
#define LEN 110
int n,tot;
char word[N+10][LEN];
int head[N+10];
struct list
{
int n;
int next;
}e[N+10];
void add(int index ,int m)
{
e[tot].n = m;
e[tot].next = head[index];
head[index] = tot++;
}
int Hash(int m)
{
int len = strlen(word[m]);
int sum = 0;
for(int i=0; i<len ; i++)
sum += (word[m][i] - 'a')*i;
return sum%N;
}
int find(char *str)
{
int len = strlen(str);
int sum = 0;
for(int i=0; i<len ;i++)
sum += (str[i] - 'a')*i;
int index = sum%N;
for(int k=head[index]; k!=-1; k=e[k].next)
{
int m = e[k].n;
if(!strcmp(word[m] , str))
return k;
}
return -1;
}
int main()
{
n = tot = 0;
memset(head,-1,sizeof(head));
while(scanf("%s",word[n])!=EOF)
{
int index = Hash(n);
add(index , n);
n++;
}
for(int i=0; i<n; i++)
{
char str1[LEN] , str2[LEN];
int len = strlen(word[i]);
for(int j=0; j<len-1; j++)
{
int k,kk;
for(k=0,kk=0; kk<=j; k++,kk++) str1[k] = word[i][kk];
str1[k] = '\0';
for(k=0,kk=j+1; kk<len; k++,kk++) str2[k] = word[i][kk];
str2[k] = '\0';
int ok[2];
ok[0] = find(str1);
ok[1] = find(str2);
if(ok[0] != -1 && ok[1] != -1)
{
printf("%s\n",word[i]);
break;
}
}
}
return 0;
}
来源:https://www.cnblogs.com/scau20110726/archive/2013/04/23/3038763.html