独自のハッシュ関数を作成する必要があります。文字列内の各文字を数値(つまり、a = 1、b = 2、c = 3、...)にマップする単純なハッシュ関数を作成したい場合、このハッシュを実行する方法はありますか?個々の文字を調べるために最初にc文字列に変換する必要のない文字列?文字列をハッシュするより効率的な方法はありますか?
最初の質問については、確かに、たとえば、次のようなものです。
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++に簡単に翻訳できます)。
個人的な経験から、これが機能し、良好な分布を生成することを私は知っています。 (盗作 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;
}
[]
演算子を使用して、std :: stringから個々の文字を調べることができます。ただし、より良いハッシュスキームのガイダンスについては、 Boost :: Functional/Hash を参照してください。 cにはハッシュ関数のリストもあります ここ 。
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;
最後の行。
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);
}
小さな文字列の別の方法:
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;
}
#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;
}
一度に4人ずつキャラクターを一緒にxorします。