Найти последовательные индексы подстроки

Учитывая строку поиска и строку результата (которая гарантированно содержит все буквы строки поиска, без учета регистра, по порядку), как я могу наиболее эффективно получить массив диапазонов, представляющих индексы в строке результата, соответствующие буквам в строке поиска?

Желаемый результат:

substrings( "word", "Microsoft Office Word 2007" )
#=> [ 17..20 ]

substrings( "word", "Network Setup Wizard" )
#=> [ 3..5, 19..19 ]
#=> [ 3..4, 18..19 ]   # Alternative, acceptable, less-desirable output

substrings( "word", "Watch Network Daemon" )
#=> [ 0..0, 10..11, 14..14 ]

Это для окна поиска с автозаполнением. Вот скриншот из инструмента , похожего на Quicksilver , который подчеркивает буквы, как я хочу. Обратите внимание, что - в отличие от моего идеального результата выше - этот снимок экрана не предпочитает более длинные одиночные совпадения.
Screenshot of Colibri underlining letters in search results

Результаты тестирования

Тестирование текущих рабочих результатов показывает, что ответ @ tokland на основе регулярных выражений в основном такой же быстрый, как и на основе StringScanner предлагаемые мной решения с меньшим количеством кода:

               user     system      total        real
phrogz1    0.889000   0.062000   0.951000 (  0.944000)
phrogz2    0.920000   0.047000   0.967000 (  0.977000)
tokland    1.030000   0.000000   1.030000 (  1.035000)

Вот тест производительности:

a=["Microsoft Office Word 2007","Network Setup Wizard","Watch Network Daemon"]
b=["FooBar","Foo Bar","For the Love of Big Cars"]
test = { a=>%w[ w wo wor word ], b=>%w[ f fo foo foobar fb fbr ] }
require 'benchmark'
Benchmark.bmbm do |x|
  %w[ phrogz1 phrogz2 tokland ].each{ |method|
    x.report(method){ test.each{ |words,terms|
      words.each{ |master| terms.each{ |term|
        2000.times{ send(method,term,master) }
      } }
    } }
  }
end

5
задан Phrogz 19 April 2011 в 19:25
поделиться