Хорошая хэш-функция для строк

Я пытаюсь придумать хорошую хэш-функцию для строк. И я подумал, что может быть хорошей идеей суммировать значения unicode для первых пяти символов в строке (при условии, что у нее пять, иначе остановитесь, где она закончится). Будет ли это хорошей идеей, или это плохо?

Я делаю это на Java, но я бы не подумал, что это будет иметь большое значение.

Ответ 1

Обычно хэши не будут делать суммы, иначе stop и pots будут иметь одинаковый хеш.

и вы не ограничили бы его первыми n символами, потому что иначе дом и дома имели бы тот же самый хеш.

Обычно хеши принимают значения и умножают их на простое число (что делает его более вероятным для создания уникальных хэшей). Таким образом, вы могли бы сделать что-то вроде:

int hash = 7;
for (int i = 0; i < strlen; i++) {
    hash = hash*31 + charAt(i);
}

Ответ 2

Если это вещь безопасности, вы можете использовать криптографию Java:

import java.security.MessageDigest;

MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(stringToEncrypt.getBytes());
String encryptedString = new String(messageDigest.digest());

Ответ 3

Вероятно, вы должны использовать String.hashCode().

Если вы действительно хотите реализовать hashCode самостоятельно:

Не поддавайтесь соблазну исключать значимые части объекта из вычисление хэш-кода для улучшения производительность - Джошуа Блох, Эффективная Java

Использование только первых пяти символов - плохая идея. Подумайте об иерархических именах, таких как URL-адреса: все они будут иметь один и тот же хэш-код (потому что все они начинаются с "http://", что означает, что они хранятся под одним и тем же ведром на карте хэша, демонстрируя ужасную производительность.

Здесь военная история перефразирована на String hashCode из Эффективная Java":

Реализована функция хеша строки во всех выпусках до 1,2 рассмотренных не более шестнадцати символов, равномерно разбросанные по всей строке, начиная с первым персонажем. Для больших коллекции иерархических имен, таких как URL-адреса, эта хеш-функция показало ужасное поведение.

Ответ 4

Если вы делаете это на Java, то почему вы это делаете? Просто вызовите .hashCode() в строке

Ответ 5

Guava HashFunction (jsdoc) обеспечивает приличное некриптовое сильное хеширование.

Ответ 6

Эта функция, предоставленная Ником, хороша, но если вы используете новую строку String (byte []) для преобразования в String, она не удалась. Вы можете использовать эту функцию для этого.

private static final char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

public static String byteArray2Hex(byte[] bytes) {
    StringBuffer sb = new StringBuffer(bytes.length * 2);
    for(final byte b : bytes) {
        sb.append(hex[(b & 0xF0) >> 4]);
        sb.append(hex[b & 0x0F]);
    }
    return sb.toString();
}

public static String getStringFromSHA256(String stringToEncrypt) throws NoSuchAlgorithmException {
    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
    messageDigest.update(stringToEncrypt.getBytes());
    return byteArray2Hex(messageDigest.digest());
}

Может быть, это может помочь кому-то

Ответ 8

FNV-1, по слухам, является хорошей хэш-функцией для строк.

Для длинных строк (длиннее, например, около 200 символов) вы можете получить хорошую производительность из MD4 хеш-функции. Как криптографическая функция, она была разрушена около 15 лет назад, но для не криптографических целей она по-прежнему очень хороша и удивительно быстро. В контексте Java вам придется преобразовать 16-разрядные значения char в 32-битные слова, например. группируя такие значения в пары. Быстрая реализация MD4 в Java можно найти в sphlib. Вероятно, излишнее в контексте задания в классе, но в противном случае стоит попробовать.

Ответ 9

sdbm: этот алгоритм был создан для библиотеки баз данных sdbm (публичная область переопределения ndbm)

static unsigned long sdbm(unsigned char *str)
{   
    unsigned long hash = 0;
    int c;
    while (c = *str++)
            hash = c + (hash << 6) + (hash << 16) - hash;

    return hash;
}

Ответ 10

Если вы хотите увидеть отраслевые стандартные реализации, я бы посмотрел на java.security.MessageDigest.

"Рассылки сообщений - это безопасные односторонние хэш-функции, которые берут данные произвольного размера и выводят хэш-значение фиксированной длины".

Ответ 11

         public String hashString(String s) throws NoSuchAlgorithmException {
    byte[] hash = null;
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        hash = md.digest(s.getBytes());

    } catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < hash.length; ++i) {
        String hex = Integer.toHexString(hash[i]);
        if (hex.length() == 1) {
            sb.append(0);
            sb.append(hex.charAt(hex.length() - 1));
        } else {
            sb.append(hex.substring(hex.length() - 2));
        }
    }
    return sb.toString();
}

Ответ 12

здесь ссылка, которая объясняет много разных хеш-функций, на данный момент я предпочитаю хеш-функцию ELF для вашей конкретной проблемы. В качестве входной информации берется строка произвольной длины.

Ответ 13

Хорошая идея работать с нечетным числом при попытке создать хорошую функцию hast для строки. эта функция принимает строку и возвращает значение индекса, пока что ее работа очень хорошая. и имеет меньшее столкновение. индекс колеблется от 0 до 300, может быть, даже больше, чем тот, но я еще не получил выше, даже с длинными словами, такими как "электромеханическая инженерия"

int keyHash(string key)
{
    unsigned int k = (int)key.length();
    unsigned int u = 0,n = 0;

    for (Uint i=0; i<k; i++)
    {
        n = (int)key[i];
        u += 7*n%31;
    }
    return u%139;
}

Другая вещь, которую вы можете сделать, - это умножение каждого символа int parse на индекс, поскольку он увеличивается, как слово "медведь", (0 * b) + (1 * e) + (2 * a) + (3 * r), который даст вам значение int, с которым можно играть. первая хеш-функция выше сталкивается при "здесь" и "слышит", но все же отлично подходит для получения хороших уникальных значений. один ниже не сталкивается с "здесь" и "слышит", потому что я умножаю каждый символ с индексом по мере его увеличения.

int keyHash(string key)
{
    unsigned int k = (int)key.length();
    unsigned int u = 0,n = 0;

    for (Uint i=0; i<k; i++)
    {
        n = (int)key[i];
        u += i*n%31;
    }
    return u%139;
}

Ответ 14

Вот простая хэш-функция, которую я использую для хэш-таблицы, которую я создал. Его в основном для приема текстового файла и сохраняет каждое слово в индексе, который представляет собой алфавитный порядок.

int generatehashkey(const char *name)
{
        int x = tolower(name[0])- 97;
        if (x < 0 || x > 25)
           x = 26;
        return x;
}

В основном это означает, что слова хэшируются в соответствии с их первой буквой. Итак, слово, начинающееся с 'a', получит хэш-ключ из 0, 'b', который получит 1 и так далее, а 'z' будет 25. Числа и символы будут иметь хэш-ключ из 26. Это преимущество, которое обеспечивает; Вы можете легко и быстро вычислить, где данное слово будет индексироваться в хеш-таблице, поскольку все это в алфавитном порядке, что-то вроде этого: Код можно найти здесь: https://github.com/abhijitcpatil/general

Предоставление следующего текста в качестве входного сигнала: Аттик сказал Джему однажды: "Идиот, вы стреляли в жестяные банки на заднем дворе, но я знаю, что вы пойдете после птиц. Выстрелите все голубые сойки, которые вы хотите, если можете ударить их, но помните его грех, чтобы убить пересмешника". Это был единственный раз, когда я когда-либо слышал, что Аттик сказал, что грех что-то сделать, и я спросил мисс Моди об этом. "Твои отцы правы", - сказала она. "Пересмешники не сделайте одно, кроме музыки для нас, чтобы наслаждаться. Они не съедают сады людей, не гнездятся в кукурузных шпаргах, они не делают ничего но петь их сердца для нас. Вот почему его грех, чтобы убить пересмешник.

Это будет выход:

0 --> a a about asked and a Atticus a a all after at Atticus
1 --> but but blue birds. but backyard
2 --> cribs corn can cans
3 --> do don’t don’t don’t do don’t do day
4 --> eat enjoy. except ever
5 --> for for father’s
6 --> gardens go
7 --> hearts heard hit
8 --> it’s in it. I it I it’s if I in
9 --> jays Jem
10 --> kill kill know
11 --> 
12 --> mockingbird. music make Maudie Miss mockingbird."
13 --> nest
14 --> out one one only one
15 --> people’s
16 --> 17 --> right remember rather
18 --> sin sing said. she something sin say sin Shoot shot said
19 --> to That’s their thing they They to thing to time the That to the the tin to
20 --> us. up us
21 --> 
22 --> why was was want
23 --> 
24 --> you you you’ll you
25 --> 
26 --> "Mockingbirds " "Your ‘em "I’d