web-dev-qa-db-ja.com

C ++を使用して文字列をintにハッシュするにはどうすればよいですか?

独自のハッシュ関数を作成する必要があります。文字列内の各文字を数値(つまり、a = 1、b = 2、c = 3、...)にマップする単純なハッシュ関数を作成したい場合、このハッシュを実行する方法はありますか?個々の文字を調べるために最初にc文字列に変換する必要のない文字列?文字列をハッシュするより効率的な方法はありますか?

16
zebraman

最初の質問については、確かに、たとえば、次のようなものです。

int hash = 0;
int offset = 'a' - 1;
for(string::const_iterator it=s.begin(); it!=s.end(); ++it) {
  hash = hash << 1 | (*it - offset);
}

2番目に関しては、文字列をハッシュするためのより良い方法がたくさんあります。たとえば、いくつかのCの例については ここ を参照してください(上記のスニペットの行に沿ってC++に簡単に翻訳できます)。

7
Alex Martelli

個人的な経験から、これが機能し、良好な分布を生成することを私は知っています。 (盗作 http://www.cse.yorku.ca/~oz/hash.html ):

djb2

このアルゴリズム(k = 33)は、何年も前にdanbernsteinによってcomp.lang.cで最初に報告されました。このアルゴリズムの別のバージョン(現在はbernsteinで支持されています)はxorを使用します:hash(i)= hash(i-1)* 33 ^ str [i];数33の魔法(素数であるかどうかにかかわらず、他の多くの定数よりもうまく機能する理由)は十分に説明されていません。

unsigned long hash(unsigned char *str) {
    unsigned long hash = 5381;
    int c;

    while (c = *str++) {
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    }

    return hash;
}
8
Tim Cooper

[]演算子を使用して、std :: stringから個々の文字を調べることができます。ただし、より良いハッシュスキームのガイダンスについては、 Boost :: Functional/Hash を参照してください。 cにはハッシュ関数のリストもあります ここ

5
wheaties

Stroustrupの本で見つけたC(++)ハッシュ関数は次のとおりです。

int hash(const char *str)
{
    int h = 0;
    while (*str)
       h = h << 1 ^ *str++;
    return h;
}

ハッシュテーブル(Stroustrupが行う)に使用している場合は、代わりに素数を法としてハッシュの絶対値を返すことができます。代わりに

    return (h > 0 ? h : -h) % N_BUCKETS;

最後の行。

5
Wren

C++ 11には、文字列の標準ハッシュ関数が付属しています。

https://en.cppreference.com/w/cpp/string/basic_string/hash

#include <string>
#include<functional> // hash
int main(){
    std::string s = "Hello";
    std::size_t hash = std::hash<std::string>{}(s);
}
1
alfC

小さな文字列の別の方法:

int hash(const char* str) {
    int hash = 0;
    int c = 0;

    while (c < std::strlen(str)) {
        hash += (int)str[c] << (int)str[c+1];
        c++;
    }
    return hash;
}
0
LUCAS
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

// a variation on dan bernstein's algorithm
// [http://www.cse.yorku.ca/~oz/hash.html]
template<typename Int>
struct hash {
    hash() : acc(5381) { }
    template<typename Ch>
    void operator()(Ch ch) { acc = ((acc << 5) + acc) ^ ch; }
    operator Int() const { return acc; }
    Int acc;
};

int main(int argc, char* argv[])
{
    string s("Hellp, world");
    cout << hex << showbase
        << for_each(s.begin(), s.end(), hash<unsigned long long>()) << '\n';
    return 0;
}
0
wilhelmtell

一度に4人ずつキャラクターを一緒にxorします。

0
Stephen