В настоящее время я пытаюсь улучшить свой алгоритм поиска.
Для лучшего понимания, вот текущая логика:
у нас есть объекты с прикрепленными n ключевых слов в дБ. в базе данных это решается с помощью 2 таблиц (Object
, Keyword
), где таблица Keyword
имеет FK до Object
. Когда я создаю свои поисковые деревья, я создаю строковое значение (объявление: удалить умные слова, преобразовать в нижний регистр, ...) из всех ключевых слов объекта. та же самая процедура преобразования (NormalizeSearchPattern()
) выполняется с шаблонами поиска. Я поддерживаю AND
-поиск и ключевые слова длиной не менее 2 символов!
Алгоритм поиска в настоящее время является вариантом fast-reverse-search
(этот пример не оптимизирован):
bool IsMatch(string source, string searchPattern)
{
// example:
// source: "hello world"
// searchPattern: "hello you freaky funky world"
// patterns[]: { "hello", "you", "freaky", "funky", "world" }
searchPattern = NormalizeSearchPattern(searchPattern);
var patterns = MagicMethodToSplitPatternIntoPatterns(searchPattern);
foreach (var pattern in patterns)
{
var success = false;
var patternLength = pattern.Length;
var firstChar = pattern[0];
var secondChar = pattern[1];
var lengthDifference = input.Length - patternLength;
while (lengthDifference >= 0)
{
if (source[lengthDifference--] != firstChar)
{
continue;
}
if (source[lengthDifference + 2] != secondChar)
{
continue;
}
var l = lengthDifference + 3;
var m = 2;
while (m < patternLength)
{
if (input[l] != pattern[m])
{
break;
}
l++;
m++;
}
if (m == patternLength)
{
success = true;
}
}
if (!success)
{
return false;
}
}
return true;
}
Нормализация выполняется с (этот пример не оптимизирован)
string RemoveTooShortKeywords(string keywords)
{
while (Regex.IsMatch(keywords, TooShortKeywordPattern, RegexOptions.Compiled | RegexOptions.Singleline))
{
keywords = Regex.Replace(keywords, TooShortKeywordPattern, " ", RegexOptions.Compiled | RegexOptions.Singleline);
}
return keywords;
}
string RemoveNonAlphaDigits(string value)
{
value = value.ToLower();
value = value.Replace("ä", "ae");
value = value.Replace("ö", "oe");
value = value.Replace("ü", "ue");
value = value.Replace("ß", "ss");
return Regex.Replace(value, "[^a-z 0-9]", " ", RegexOptions.Compiled | RegexOptions.Singleline);
}
string NormalizeSearchPattern(string searchPattern)
{
var resultNonAlphaDigits = RemoveNonAlphaDigits(searchPattern);
var resultTrimmed = RemoveTooShortKeywords(resultNonAlphaDigits);
return resultTrimmed;
}
Так что это довольно просто, поэтому очевидно, что я могу справиться только с вариантами source
и searchPattern
, которые я реализовал в NormalizeSearchPattern()
(как упомянуто выше: умлауты, различия в регистре,… ).
Но как мне улучшить алгоритм (или NormalizeSearchPattern()
), чтобы он был нечувствительным, когда он сводится к:
- единственном / множественном
- misstyping (например, "hauserr" <-> "hauser")
- ...
Просто чтобы узнать больше о дизайне:
Это приложение выполнено на языке c #, оно хранит деревья поиска и объекты в статической переменной (чтобы запросить базу данных только один раз при инициализации), производительность должна быть выдающейся (в настоящее время 500 000 строк-значений запрашиваются в течение менее 300 мс).