What's a good hash function for English words?

后端 未结 4 647
情书的邮戳
情书的邮戳 2020-11-27 19:17

I have a long list of English words and I would like to hash them. What would be a good hashing function? So far my hashing function sums the ASCII values of the letters the

相关标签:
4条回答
  • 2020-11-27 19:58

    A bit late, but here is a hashing function with an extremely low collision rate for 64-bit version below, and ~almost~ as good for the 32-bit version:

    uint64_t slash_hash(const char *s)
    //uint32_t slash_hash(const char *s)
    {
        union { uint64_t h; uint8_t u[8]; } uu;
        int i=0; uu.h=strlen(s);
        while (*s) { uu.u[i%8] += *s + i + (*s >> ((uu.h/(i+1)) % 5)); s++; i++; }
        return uu.h; //64-bit
        //return (uu.h+(uu.h>>32)); //32-bit
    }
    

    The hash-numbers are also very evenly spread across the possible range, with no clumping that I could detect - this was checked using the random strings only.
    [edit]
    Also tested against words extracted from local text-files combined with LibreOffice dictionary/thesaurus words (English and French - more than 97000 words and constructs) with 0 collisions in 64-bit and 1 collision in 32-bit :)

    (Also compared with FNV1A_Hash_Yorikke, djb2 and MurmurHash2 on same sets: Yorikke & djb2 did not do well; slash_hash did slightly better than MurmurHash2 in all the tests)

    0 讨论(0)
  • 2020-11-27 19:59

    To simply sum the letters is not a good strategy because a permutation gives the same result.

    This one (djb2) is quite popular and works nicely with ASCII strings.

    unsigned long hashstring(unsigned char *str)
    {
        unsigned long hash = 5381;
        int c;
    
        while (c = *str++)
            hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    
        return hash;
    }
    

    More info here.

    If you need more alternatives and some perfomance measures, read here.

    Added: These are general hashing functions, where the input domain is not known in advance (except perhaps some very general assumptions: eg the above works slightly better with ascii input), which is the most usual scenario. If you have a known restricted domain (set of inputs fixed) you can do better, see Fionn's answer.

    0 讨论(0)
  • 2020-11-27 20:17

    Maybe something like this would help you: http://www.gnu.org/s/gperf/

    It generates a optimized hashing function for the input domain.

    0 讨论(0)
  • 2020-11-27 20:20

    If you don't need it be cryptographically secure, I would suggest the Murmur Hash. It's extremely fast and has high diffusion. Easy to use.

    http://en.wikipedia.org/wiki/MurmurHash

    http://code.google.com/p/smhasher/wiki/MurmurHash3

    If you do need a cryptographically secure hash, then I suggest SHA1 via OpenSSL.

    http://www.openssl.org/docs/crypto/sha.html

    0 讨论(0)
提交回复
热议问题