Задача:
Есть таблица некоторых критериев, которая имеет следующий вид:
A1 A2 ... A40
B1 B2 ... B40
...
Количество строк может быть около 40000.
Значение каждой ячейки -- произвольная строка (до 256 символов). Также есть специальное значение -- "*" (зведочка).
Теперь есть запрос:
Z1 Z2 ... Z40
Значения полей запроса аналогичны по структуре ячейкам таблицы, включая специальное значение.
Проверка запроса: надо найти среди строк исходной таблицы максимально совпадающую со значениями запроса. Специальное значение "*" либо в запросе, либо в таблице, означает совпадение в данной ячейке вне засимости от значения, с которым сравнивают.
Например:
XYZ GBP 123 * [все значения -- *] *
XYZ USD 123 * [все значения -- *] *
XYZ USD * * [все значения -- *] *
* * * * [все значения -- *] *
Запрос:
XYZ USD 567 * [все значения -- *] *
Ответом должна быть строка номер 3.
При банальном подходе можно просто заранее отсортировать строки таблицы по убыванию количества конкретных значений, и уже для каждого запроса проверять посрочно до первого удачного совпадения. Получается 40000*40 сравнений (не будем учитывать время сравнения самих ячеек).
Может тут как-то можно ускорить, используя результаты предыдущей строки? Например, обработав строку 2, мы знаем, что первые два поля уже совпадают, и может быть их можно уже не сравнивать... Можно индекс какой построить. Ограничения на память особых нет.
Можно даже сгенерить некий код-парсер, которых будет представлять логику конкретной исходной таблицы. Вот только вопрос, в чем должна быть идея этого парсера.
Подумал над несколькими вариантами, но везде лажа выходит. и по времени и по памяти. непонятно что за природа таблицы и запросов, возможно зная её можно придумать что-то по-лучше для вашего случая. Могу предложить метод с такой же сложностью что и ваш, который делает некоторые отсечения при удачном раскладе, но требует препроцессинга таблицы и использования хеш-таблиц либо замены строк на числа. посортим столбцы как-нибудь имперически-эвристически оптимально. все строки в ячейках заменим на числа. строим бор для строк таблицы. имея строку-запрос начинаем поиск в ширину по нашему бору. состояние описывается вершиной бора, и количеством совпавших ячеек. заведем глобальную переменную отвечающую за максимум совпадений на данном шаге. на завершающей стадии поиска в ширину возникают отсечение, если мы уже никак не доберём нужное число совпадений, улучшающее максимум. можно юзать 40 очередей для "дейкстры", чтобы идти по бору глубже пока есть совпадения.
гоню в предыдущей правке.
Можно использовать что-то вроде бора. Предположим что каждому атрибуту выдано число (номер буквы в алфавите). Каждая строка -- некоторое слово из 40 букв. После построения бора пускаем по нему 0-1_бфс. Если надо перейти по букве, где нет совпадения, то вес ребра единица, иначе 0. В худшем случае работает так же плохо, но если строка-запрос отличается от ответа на небольшое число символов, то должно работать хорошо.
Для "совсем общего" случая алгоритма хорошего вероятно не будет, а частности у вас не описаны: насколько схожи между собой строки таблицы, как много среди них звёздочек, как много у вас запросов, сколько вам надо времени на запрос и т.п.
Кроме того непонятна относительная ценность совпадения буква-буква и буква-звёздочка (а также звёздочка-буква). Скажем запрос "A B C" идеально совпадает со строкой "* * *", а со строкой "A B V" он совпадает неидеально, зато две буквы верные.
Могу предложить алгоритм для "довольно общего" случая, например пусть у нас M строк по N ячеек:
для каждого столбца подготовим массив индексов строк, отсортированный по возрастанию ячеек в этом столбце.
Для обработки запроса, подготовим массив R результата, т.е. массив оценок для каждой из строк, длиной M чисел, изначально там нули.
Когда имеем запрос, то для каждого K-го (K=1..N) массива за O(log(M)) находим пару индексов A и B, между которыми лежат все номера строк, в которых K-я ячейка совпадает с K-й ячейкой из запроса.
Пробегаем по полученному диапазону индексов и для каждого индекса I увеличиваем R[I] на единицу.
Совпадение со звёздочками обрабатываем отдельно, аналогично, только увеличивать можно не на единицу, а на стоимость совпадения со звёздочкой.
В конце отыскиваем максимум в массиве R. Эта позиция соответствует "оптимальной" строке.
Быстродействие, очевидно, зависит от того как много похожих ячеек в строках. Если все строки одинаковы и запрос совпадает с ними со всеми, мы получим нечто слегка похуже O(M*N). Если много различающихся строк, то массив R будет забиваться за время стремящееся к O(log(M)*N) — если совпадений по 1 на столбец — и потом поиск лучшего варианта за O(N) — его тоже можно уменьшить вплоть до O(M) если R представить хэшмэпой.
В общем, всё от характера данных зависит. Возможно вам и не нужна оптимизация %)
можно использовать БД.
Что такое БД?
Базы данных, наверное...