#algorithm #hash
#алгоритм #хэш
Вопрос:
Я читаю эту статью в этой статье говорится о хешировании строк. В разделе «Поиск повторяющихся строк в массиве строк» утверждается, что вы можете группировать идентичные строки с временной сложностью O(M*N*log(N))
, используя хеширование строк.
Глядя на этот пример кода, представленный в статье
vector<vector<int>> group_identical_strings(vector<string> constamp; s) {
int n = s.size();
vector<pair<long long, int>> hashes(n);
for (int i = 0; i < n; i )
hashes[i] = {compute_hash(s[i]), i};
sort(hashes.begin(), hashes.end());
vector<vector<int>> groups;
for (int i = 0; i < n; i ) {
if (i == 0 || hashes[i].first != hashes[i-1].first)
groups.emplace_back();
groups.back().push_back(hashes[i].second);
}
return groups;
}
Я очень смущен тем, насколько этот код будет правильным, потому что он создает новую группу только при условии, что hashes[i].first != hashes[i-1].first
. Две строки могут быть разными, но иметь одинаковые хэши, и поэтому две строки могут быть добавлены в одну и ту же группу, даже если они разные? Это условие мне кажется недостаточным.
Я ошибаюсь? Правильный ли этот код? Почему?
Если нет, то действительно ли этот алгоритм или, по крайней мере, эта сложность достижима?
Комментарии:
1. По этой же причине мы говорим, что хэш-таблицы амортизировали поиск O (1). Конечно, естественно, могут возникнуть коллизии, и нам придется прибегнуть к какой-то другой (вероятно, не O (1)) процедуре, чтобы различать ключи 2 , разделяющие хэш. Однако, по статистике, это должно происходить достаточно редко и с достаточным количеством членов на столкновение, чтобы мы могли сказать, что в целом амортизированная временная сложность по-прежнему равна O ((1) .
Ответ №1:
Вы совершенно правы, что две разные строки могут иметь одинаковый хэш. Это называется столкновением хэшей. Однако это сводится к тому, какую хэш-функцию вы используете. Существуют хеш-функции, для которых обнаружение коллизии настолько маловероятно, что вы можете использовать этот алгоритм, не опасаясь его нарушения. В криптографии мы полагаемся на это свойство криптографически безопасных хеш-функций (см., Например, Здесь ).
Фактически, в самом источнике, который вы упомянули, указано следующее:
Это важная часть, которую вы должны иметь в виду. Использование хеширования не будет на 100% детерминированно корректным, потому что две совершенно разные строки могут иметь один и тот же хэш (хэши сталкиваются). Однако в подавляющем большинстве задач это можно смело игнорировать, поскольку вероятность столкновения хэшей двух разных строк все еще очень мала. И в этой статье мы обсудим некоторые методы, как сохранить вероятность столкновений на очень низком уровне.
Таким образом, алгоритм, как вы говорите, не математически корректен. Но при правильном выборе хэш-функции вероятность ее сбоя на практике ничтожно мала.