C 字符串的多项式散列与循环多项式移位

C 字符串的多项式散列与循环多项式移位,c,data-structures,hash,C,Data Structures,Hash,我将此函数用于循环移位: int hashcyclic(char *p, int len) { unsigned int h = 0; int i; for (i = 0; i < len; i++) { h = (h << 5) | (h >> 27); h += (unsigned int)p[i]; } return h%TABLESIZE; } 现在我在20K字文件上得到了25K左右的碰撞,在40

我将此函数用于循环移位:

int hashcyclic(char *p, int len)
{
   unsigned int h = 0;
   int i;
   for (i = 0; i < len; i++)
   {
      h = (h << 5) | (h >> 27);
      h += (unsigned int)p[i];
   }
   return h%TABLESIZE;
}
现在我在20K字文件上得到了25K左右的碰撞,在40K字文件上得到了901K左右的碰撞(几乎是循环移位的12倍)

我的问题是,这有意义吗?还是我的一个实现搞砸了?我希望我的字符串(40K单词文件是一系列由8个字母组成的单词,以换行符分隔)的循环速度最快,但多项式面临的冲突要少得多

int HashInsertPoly(Table T, KeyType K, InfoType I)
{
   int i;
   int ProbeDecrement;
   i = hashpoly(K);
   ProbeDecrement = p(K);

   while (T[i].Key[0] != EmptyKey)
   {
      totalcol++;
      T[i].Info.col++;
      i -= ProbeDecrement;
      if (i < 0)
         i += TABLESIZE;
   }

   strcpy(T[i].Key, K);
   insertions++;

   /*T[i].Info = I;*/

   return i;
}
int HashInsertPoly(表T,键类型K,信息类型I)
{
int i;
智力测验;
i=hashpoly(K);
ProbeDecrement=p(K);
while(T[i].Key[0]!=EmptyKey)
{
totalcol++;
T[i].Info.col++;
i-=概率增量;
if(i<0)
i+=表大小;
}
strcpy(T[i].Key,K);
插入++;
/*T[i].Info=i*/
返回i;
}

相同的HashInsert函数适用于具有循环移位的哈希,除了现在我调用hashcyclic而不是hashpoly

我的直觉是纯文本单词的变化不高,因此循环哈希不够混乱

让我们看两个字符串“猫”和“狗”

因为ASCII范围很小,循环算法使用无符号整数的整个空间,所以需要长字符串才能将哈希真正推入完全不同的空间。特别是最后一个字符,它真正支配着最终的模运算

另一种看待它的方式是:当你将7位ASCII字符和之前的7位ASCII字符中的5位移开并替换为0后,它们之间几乎没有交互作用,特别是对于较短的字

因为多项式散列只使用表大小,所以它的混沌“更快”,即使对于较小的字符串也是如此。在它开始变得非常混乱之前,它不需要填充一个整数。单个ASCII字符比表大得多


无论如何,这是我的猜测。我会通过检查哪些字符串发生冲突来确认这一点。我的猜测是,长度相似的字符串与循环算法的冲突最大。

我的直觉是,纯文本单词的变化不大,因此循环哈希不够混乱

让我们看两个字符串“猫”和“狗”

因为ASCII范围很小,循环算法使用无符号整数的整个空间,所以需要长字符串才能将哈希真正推入完全不同的空间。特别是最后一个字符,它真正支配着最终的模运算

另一种看待它的方式是:当你将7位ASCII字符和之前的7位ASCII字符中的5位移开并替换为0后,它们之间几乎没有交互作用,特别是对于较短的字

因为多项式散列只使用表大小,所以它的混沌“更快”,即使对于较小的字符串也是如此。在它开始变得非常混乱之前,它不需要填充一个整数。单个ASCII字符比表大得多


无论如何,这是我的猜测。我会通过检查哪些字符串发生冲突来确认这一点。我猜长度相似的字符串与循环算法的冲突最大。

表大小的值很重要。这是怎么一回事?我不知道你在散列什么,但你不能通过散列20k个单词来实现45187次碰撞。你能做的最糟糕的事情就是有20k次碰撞。我的意思是在插入了所有40K个单词后的总数。表大小设置为41893。一次插入的最大碰撞次数是975次循环多项式,最糟糕的是一次插入的碰撞次数是108次。这有意义吗?TABLESIZE的值很重要。这是怎么一回事?我不知道你在散列什么,但你不能通过散列20k个单词来实现45187次碰撞。你能做的最糟糕的事情就是有20k次碰撞。我的意思是在插入了所有40K个单词后的总数。表大小设置为41893。一次插入的最大碰撞次数是975次循环多项式,最糟糕的是一次插入的碰撞次数是108次。这有意义吗?我的'hard.txt'文件中的行都是相同长度的(如'abcdefg','abdcefg','adbcefg','adbcefg'),总共有12米的循环移位冲突。900K带多项式。在我的“EnglishWords.txt”文件中,循环移位(每个单词的长度不一样)和多项式的碰撞大约有50K。所以我想这是有道理的?尽管多项式还是少了一点。我的'hard.txt'文件中的行都是相同长度的(如'abcdefg'、'abdcefg'、'adbcefg'等变体),并且总共有12米的循环移位冲突。900K带多项式。在我的“EnglishWords.txt”文件中,循环移位(每个单词的长度不一样)和多项式的碰撞大约有50K。所以我想这是有道理的?即使多项式还是少了一点。
int HashInsertPoly(Table T, KeyType K, InfoType I)
{
   int i;
   int ProbeDecrement;
   i = hashpoly(K);
   ProbeDecrement = p(K);

   while (T[i].Key[0] != EmptyKey)
   {
      totalcol++;
      T[i].Info.col++;
      i -= ProbeDecrement;
      if (i < 0)
         i += TABLESIZE;
   }

   strcpy(T[i].Key, K);
   insertions++;

   /*T[i].Info = I;*/

   return i;
}
cat 

c 01100011
a 01100001
t 01110100

h starts at 
00000000 00000000 00000000 01100011 (c)
and is then cycled to 
00000000 00000000 00001100 01100000
then we add `a` to get
  00000000 00000000 00001100 01100000
+                            01100001
= 00000000 00000000 00001100 11000001
which is then cycled to
00000000 00000001 10011000 00100000
then we add `t` to get 
  00000000 00000001 10011000 00100000
+                            01110100
= 00000000 00000001 10011000 10010100
we then return this number mod 41893 for 20810

Similarly, for dog

d 01100100
o 01101111
g 01100111

start: 
00000000 00000000 00000000 01100100 (d)
cycled and added o:
00000000 00000000 00001100 11101111
cycled and added t:
00000000 00000001 10011110 01000111
ends up at 22269