哈希
题意简短:单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; }