Próbuję wymyślić dobrą funkcję mieszającą dla ciągów. Pomyślałem, że dobrym pomysłem może być podsumowanie wartości Unicode dla pierwszych pięciu znaków w ciągu (zakładając, że ma pięć, w przeciwnym razie zatrzymaj się tam, gdzie się kończy). Czy to byłby dobry pomysł, czy zły?
Robię to w Javie, ale nie wyobrażam sobie, że miałoby to duże znaczenie.
String
własnegohashCode()
?Odpowiedzi:
Zazwyczaj mieszań nie robić sum, inaczej
stop
ipots
będą miały ten sam hash.i nie ograniczyłbyś go do pierwszych n znaków, ponieważ w przeciwnym razie house i domy miałyby ten sam skrót.
Generalnie hashy pobierają wartości i mnożą je przez liczbę pierwszą (zwiększa prawdopodobieństwo generowania unikalnych haszów), więc możesz zrobić coś takiego:
źródło
Jeśli jest to kwestia bezpieczeństwa, możesz użyć Java Crypto:
źródło
Prawdopodobnie powinieneś użyć String.hashCode () .
Jeśli naprawdę chcesz sam zaimplementować hashCode:
Używanie tylko pierwszych pięciu znaków to zły pomysł . Pomyśl o nazwach hierarchicznych, takich jak adresy URL: wszystkie będą miały ten sam kod skrótu (ponieważ wszystkie zaczynają się od „http: //”, co oznacza, że są przechowywane w tym samym zasobniku na mapie skrótów, wykazując straszną wydajność.
Oto historia wojenna sparafrazowana na podstawie kodu skrótu String z „ Effective Java ”:
źródło
Jeśli robisz to w Javie, dlaczego to robisz? Wystarczy wezwać
.hashCode()
sznurekźródło
.hashCode()
. Zamiast tego użyj jakiegoś znanego algorytmu.String::hashCode
jest określony w JDK, więc jest tak przenośny, jak samo istnienie klasyjava.lang.String
.Guava
HashFunction
( javadoc ) zapewnia przyzwoity haszowanie bez szyfrowania.źródło
404
d.Ta funkcja dostarczona przez Nicka jest dobra, ale jeśli użyjesz new String (bajt [] bajtów) do przekształcenia w String, nie powiodła się. Możesz użyć tej funkcji, aby to zrobić.
Może to komuś pomoże
źródło
source Logika funkcji skrótu djb2 - SO
źródło
Mówi się, że FNV-1 jest dobrą funkcją mieszającą dla ciągów znaków.
W przypadku długich łańcuchów (dłuższych niż, powiedzmy, około 200 znaków) można uzyskać dobrą wydajność z funkcji skrótu MD4 . Jako funkcja kryptograficzna została zerwana około 15 lat temu, ale do celów niekryptograficznych nadal jest bardzo dobra i zaskakująco szybka. W kontekście Javy należałoby zamienić wartości 16-bitowe
char
na słowa 32-bitowe, np. Grupując takie wartości w pary. Szybką implementację MD4 w Javie można znaleźć w sphlib . Prawdopodobnie przesada w kontekście zadania w klasie, ale poza tym warto spróbować.źródło
Jeśli chcesz zobaczyć standardowe implementacje branżowe, przyjrzyj się java.security.MessageDigest .
„Digesty wiadomości to bezpieczne jednokierunkowe funkcje skrótu, które pobierają dane o dowolnej wielkości i wyświetlają wartość skrótu o stałej długości”.
źródło
tutaj jest link, który wyjaśnia wiele różnych funkcji skrótu, na razie wolę funkcję skrótu ELF dla twojego konkretnego problemu. Jako dane wejściowe przyjmuje ciąg o dowolnej długości.
źródło
sdbm: ten algorytm został stworzony dla biblioteki baz danych sdbm (reimplementacja domeny publicznej ndbm)
źródło
źródło
Dobrym pomysłem jest praca z liczbą nieparzystą podczas próby opracowania dobrej funkcji przyspieszającej dla łańcucha. ta funkcja przyjmuje ciąg znaków i zwraca wartość indeksu, na razie działa całkiem nieźle. i ma mniej kolizji. indeks waha się od 0 do 300, może nawet więcej, ale jak dotąd nie doszedłem wyżej, nawet przy długich słowach, takich jak „inżynieria elektromechaniczna”
inną rzeczą, którą możesz zrobić, jest pomnożenie każdego znaku int parse przez indeks, gdy będzie on zwiększany jak słowo "niedźwiedź" (0 * b) + (1 * e) + (2 * a) + (3 * r), co da ci wartość int do zabawy. pierwsza funkcja skrótu powyżej zderza się w miejscu „tutaj” i „słyszysz”, ale nadal świetnie daje dobre, unikalne wartości. ten poniżej nie koliduje z „tutaj” i „słyszysz”, ponieważ mnożę każdy znak wraz ze wzrostem indeksu.
źródło
Oto prosta funkcja skrótu, której używam do zbudowanej przeze mnie tabeli skrótów. Zasadniczo służy do pobierania pliku tekstowego i przechowywania każdego słowa w indeksie, który reprezentuje porządek alfabetyczny.
Zasadniczo to oznacza, że słowa są haszowane zgodnie z ich pierwszą literą. Zatem słowo zaczynające się od „a” otrzyma klucz krzyżyka równy 0, „b” otrzyma 1 itd., A „z” będzie równe 25. Liczby i symbole miałyby klucz krzyżyka 26. Jest to zaleta ; Możesz łatwo i szybko obliczyć, gdzie dane słowo byłoby indeksowane w tabeli skrótów, ponieważ jest w porządku alfabetycznym, coś takiego: Kod można znaleźć tutaj: https://github.com/abhijitcpatil/general
Byłby to wynik:
źródło
Pozwoli to uniknąć kolizji i będzie działać szybko, dopóki nie użyjemy przesunięcia w obliczeniach.
źródło