Действительно ли бинарный поиск в таблице так ужасен?Я бы взял список потенциальных строк и «свернул» их, отсортировал их и, наконец, выполнил бы бинарный поиск по их блоку.
Под минимизацией я подразумеваю сокращение их до минимума, которым они должны быть,своего рода пользовательский стемминг.
Например, если бы у вас были строки: «Альфред», «Боб», «Билл», «Джо», я бы выбил их до «а», «би», "bo", "j".
Затем поместите их в непрерывный блок памяти, например:
char *table = "a\0bi\0bo\0j\0"; // last 0 is really redundant..but
char *keys[4];
keys[0] = table;
keys[1] = table + 2;
keys[2] = table + 5;
keys[3] = table + 8;
В идеале компилятор сделает все это за вас, если вы простоgo:
keys[0] = "a";
keys[1] = "bi";
keys[2] = "bo";
keys[3] = "j";
Но я не могу сказать, правда это или нет.
Теперь вы можете найти эту таблицу, и ключи будут максимально короткими.Если вы нажмете на конец ключа, вы соответствуете.Если нет, то следуйте стандартному алгоритму bsearch.
Цель состоит в том, чтобы собрать все данные близко друг к другу и сохранить крошечный код, чтобы он вписывался в кэш ЦП.Вы можете обработать ключ непосредственно из программы, без предварительной обработки или добавления чего-либо.
Для достаточно большого количества ключей, которые разумно распределены, я думаю, что это будет довольно быстро.Это действительно зависит от количества задействованных строк.Для меньших чисел затраты на вычисление хеш-значений и т. Д. Больше, чем поиск чего-то подобного.Для больших значений оно того стоит.Какое это число будет зависеть от алгоритмов и т. Д.
Это, однако, вероятно, наименьшее решение с точки зрения памяти, если это важно.
Это также имеет преимущество простоты.
Дополнения:
У вас нет никаких спецификаций на входах, кроме «строк».Также не обсуждается, сколько строк вы планируете использовать, их длину, общность или частоту использования.Возможно, все они получены из «источника», но не запланированы разработчиком алгоритма.Вы запрашиваете алгоритм, который создает что-то вроде этого:
inline int GetValue(char *key) {
return 1234;
}
Для небольшой программы, в которой все время используется только один ключ, вплоть до чего-то, что создает идеальный алгоритм хеширования длямиллионы строк.Это довольно высокий порядок.
Любой дизайн, который стремится к «сжатию каждого возможного бита производительности», должен знать больше о входных данных, чем «любые строки».Это проблемное пространство просто слишком велико, если вы хотите, чтобы оно было максимально быстрым для любого условия.
Алгоритм, обрабатывающий строки с очень длинными одинаковыми префиксами, может сильно отличаться от алгоритма, который работает с совершенно случайными строками.Алгоритм может сказать «если ключ начинается с« а », пропустить следующие 100 символов, так как они все« а »».
Но если эти строки получены людьми, и они используют длинные строки с одинаковыми буквами и не сходят с ума, пытаясь сохранить эти данные, тогда, когда они жалуются, что алгоритм работает плохо, выответьте, что «вы делаете глупости, не делайте этого».Но мы также не знаем источник этих строк.
Итак, вам нужно выбрать проблемное место для цели алгоритма.У нас есть все виды алгоритмов, которые якобы делают одно и то же, потому что они решают разные проблемы и работают лучше в разных ситуациях.
Хеширование обходится дорого, а размещение хеш-карт обходится дорого.Если данных недостаточно, есть лучшие методы, чем хеширование.Если у вас большой бюджет памяти, вы можете создать огромный конечный автомат, основанный на N состояниях на узел (N - это размер набора символов, который вы не указываете - BAUDOT? 7-битный ASCII? UTF-32?),Это будет выполняться очень быстро, если только объем памяти, потребляемый состояниями, не разрушит кэш ЦП или не вытеснит другие вещи.
Возможно, вы сгенерируете код для всего этого, но вы можете работать с ограничениями по размеру кода.(Вы также не говорите, на каком языке - например, Java имеет ограничение в байтовом коде для метода 64K).
Но вы не указываете ни одно из этих ограничений. Поэтому сложно найти наиболее эффективное решение для ваших нужд.