Недавно я пытался решить следующую проблему:Построение множества уникальных строк в файле эффективно, без сохранения фактических строк в наборе
У меня есть очень большой файл, содержащий длинные строки, и мне нужно найти и распечатать все уникальные строки в нем.
Я не хочу использовать карту или задавать сохранение фактических строк, так как файл очень большой и длинные строки, поэтому это приведет к сложности пространства O (N) с плохими константами (где N количество строк). Предпочтительно, я предпочел бы генерировать набор, сохраняющий указатели на строки в уникальных файлах. Очевидно, что размер такого указателя (8 байт на 64-битной машине, который, как я полагаю), обычно намного меньше размера строки (1 байт на символ, который, как мне кажется) в памяти. Хотя пространственная сложность все еще O (N), константы теперь намного лучше. Используя эту реализацию, файл никогда не должен полностью загружаться в память.
Теперь, допустим, я просмотрю файл по строкам, проверяя уникальность. Чтобы узнать, уже ли он в наборе, я мог бы сравнить со всеми строками, указанными в наборе, сравнивая символ по символу. Это дает сложность O (N^2 * L), при этом L - средняя длина линии. Когда вы не заботитесь о сохранении полных строк в наборе, сложность O (N * L) может быть достигнута благодаря хешированию. Теперь, когда вместо этого используется набор указателей (чтобы уменьшить требования к пространству), как я могу достичь этого? Есть ли опрятный способ сделать это? Единственное, что я могу придумать, это такой подход:
- Хеш-предложение. Сохраните хеш-значение для сопоставления (или на самом деле: unordered_multimap unordered, чтобы получить стиль hashmap, multi, поскольку двойные ключи могут быть вставлены в случае «ложных совпадений»).
- Для каждого нового предложения: проверьте, находится ли его хэш-значение на карте. Если нет, добавьте его. Если да, сравните полные предложения (новый и один в неупорядоченной карте с одинаковым хэшем) по символу, чтобы убедиться, что нет «ложного совпадения». Если это «ложное совпадение», добавьте его еще.
Это правильный путь? Или вы можете сделать это лучше? Все предложения приветствуются!
И могу ли я использовать какой-то умный «объект сравнения» (или что-то в этом роде, о котором я пока мало знаю), чтобы эта проверка для уже существующих предложений была полностью автоматизирована при каждом вызове unordered_map :: find()?
Можете ли вы дать приблизительную оценку количества строк вашего файла и/или общего размера файла? – MikeMB
Вы говорите, что полный файл хранится в памяти в другом месте, поэтому вы можете указать на него? –