2012-04-18 3 views
0

Имейте слова из OCR и вам нужен список близких совпадений. Может жить без maxFrom. Пример кода - грубая сила, но, надеюсь, он определяет это требование. Против списка 600 000 это занимает 2 секунды. FTSword.Word - это строка.LINQ Чтобы найти частичные совпадения

В идеале «findd» предоставит дополнительный кредит на второй d. И как только он находит i, тогда f не получает никакого кредита. Грубая сила, я могу это сделать. Я ищу, чтобы сделать это 2 секунды вниз. Будет проверять и сообщать о любом предлагаемом решении.

Вопрос ?? является. Как сделать это быстрее? (И умнее)

Благодаря

  char[] find = new char[] { 'f', 'i', 'n', 'd' }; 
      char[] word; 
      int maxFrom = 10; 
      int minMatch = 3; 
      int count; 
      List<FTSword> matchWords = new List<FTSword>(); 
      foreach (FTSword ftsw in fTSwords) 
      { 
       if (ftsw.Word.Length < maxFrom) 
       { 
        word = ftsw.Word.ToCharArray(); 
        count = 0; 
        foreach (char fc in find) 
        { 
         foreach (char wc in word) 
         { 
          if (char.ToLower(wc) == char.ToLower(fc)) 
          { 
           count++; 
           break; 
          } 
         } 
        } 
        if (count >= minMatch) 
        { 
         // Debug.WriteLine(count.ToString() + ftsw.Word); 
         matchWords.Add(ftsw); 
        } 
       } 
      } 
      Debug.WriteLine(matchWords.Count.ToString()); 
+0

И ваш вопрос? –

+1

Здесь вы можете найти подходы к предварительной калькуляции данных для получения более быстрых результатов поиска: http://stackoverflow.com/questions/10096744/puzzle-solving-finding-all-words-within-a-larger-word-in-php/ 10096985 # 10096985. В идеале вы либо уменьшаете количество операций на слово, как в этом примере, либо уменьшаете пространство поиска, индексируя или разделяя ненужные слова. – mellamokb

+0

@mellamokb, эта ссылка касается внутренних совпадений, но не начисляет частичную. – Paparazzi

ответ

1

Ваш основной алгоритм в настоящее время O (N^2), так как у вас есть два вложенных цикл подберут символы. Вы можете легко сделать эту часть O (п) с помощью словаря, который содержит счетчики символов для каждого символа в find строки:

string find = "find"; 
var findMap = new Dictionary<char, int>(); 
foreach (char c in find) 
{ 
    if (findMap.ContainsKey(c)) 
    { 
     findMap[c] = findMap[c] + 1; 
    } 
    else 
     findMap.Add(c, 1); 
} 
//findMap is pre-generated once 

string word = "pint"; 
int count = 0; 

//runs for each word in list, now in O(n) 
foreach(char c in word) 
{ 
    int charCount; 
    if(findMap.TryGetValue(c, out charCount)) 
    { 
     if(charCount > 0) 
     { 
      charCount--; 
      findMap[c] = charCount; 
      count++; 
     } 
    } 
} 
+0

Сравнение O() на таком маленьком «n» вводит в заблуждение/бесполезно. За исключением профилирования, нет способа доказать, что это быстрее, чем подход в вопросе. Возможно, это может быть, или может быть и не так. –

+0

Это сокращает время в 1/2 и учитывает несколько совпадений одного и того же символа. Что пропускает регистр без учета регистра. Благодаря! Я надеялся на магию LINQ в миллисекундах, но это будет сделано. – Paparazzi

1

Вы можете удалить char.ToLower() на ФХ, если вы убедитесь, что это в нижнем регистре перед вами Начало.

Вы также можете попробовать использовать IndexOf(), чтобы найти первое (а затем последующее вхождение символа), поскольку реализация BCL может быть внутренне быстрее, чем вы можете управлять с помощью своего собственного цикла.

Вы также можете попробовать запустить свою петлю в обратном направлении, которое может обеспечить ускорение:

for (int i = arr.Length - 1; i >= 0; i--) 

Но на самом деле, для распознавания текста, почему бы вы подытожить соответствие символов из произвольных позиций в строке вместо того, чтобы делать истинное редактирование расстояние, например Damerau-Levenshtein?

+0

Ссылка на редактирование расстояния, если очень интересно. В OCR мы также получаем два слова, конкатенированные, и это не касается этого, но я могу быть достаточно умным, чтобы изменить его. – Paparazzi

+0

Мне нужно использовать что-то более продвинутое, так как простое количество попаданий недостаточно избирательно. пример совпадает с домашней таблицей до 6 символов – Paparazzi

+0

Этот алогорит бежал за 6 секунд против 600 000. Медленнее, но это дает весомый ответ. Как я уже говорил, он не занимается конкатенациями OCR, но для этого он не предназначен. благодаря – Paparazzi

Смежные вопросы