Вначале, все слова записываем в виде хеша так, чтобы буквы шли по-порядку, но повторные - не повторялись. 'мама мыла раму' => 'ма ылру'
Можно дополнительно создать еще один кэш и отсортировать в порядке убывания кол-во повторов букв:
Приведём новый пример: 'мыла раму мама' (переставим слова местами)
'мыла раму мама' => [м-4][ы-1][л-1][а-4][(пробел)-2][р-1][у-1]=>'ма ылру' (предыдущий пример останется без изменений...)
и поиск вести по половинам хэша (при нечетном кол-ве -округляем в большую сторону) введённой строки 'ма ылру':
1. При не найденных совпадениях, порядок такой: 'ма ы'=>'ма'=>'м'
2. При найденных совпадениях, порядок такой: 'ма ылр'=>'ма ыл' Как выдача будет нулевая - берём предыдущий МИНИМАЛЬНЫЙ! результат выдачи.
Таким образом можно отловить с большей вероятностью пропущенные буквы при вводе.
Можно составить отдельную таблицу по всем словам и привязать их к основным данным.
Затем выборка этажеркой:
1. Преобразуем так же вводимую строку и выбираем LIKE 'ма мыл%'
(возможно несколько выборок с проверкой пропущенной буквы) запоминая результат выборки.
2. По этому результату ищем полную строку с тем же LIKE 'мама мыла раму%'
3. При следующем поиске, если хэш не уменьшился и символы в диапазоне длины предыдущего хэша не изменились - мы ищем СРАЗУ ЖЕ! по результату п.1 (и снова запоминаем результат), экономя время (т.е. поиск как бы идёт по предыдущему кэшу).
Таким образом получается, что чем больше букв, тем меньше записей мы перебираем.
А чем меньше мы перебираем, тем больше у нас времени остаётся и мы можем его использовать на дополнительные запросы: для нечеткого поиска.