Лекции по информатике (984119), страница 14
Текст из файла (страница 14)
Сложностная оценка прямого поиска по образцу находится в диапазоне от 01ЛХ) или 01%), когда образец встречается сразу или его первая буква появляется в конце последовательности либо не появляется вообще, и до 01% ЛХ, когда, и образец, и последовательность содержат общий повторякицийся участок. В последнем случае в цепочке, например, .из 1У вЂ” 1 букв а с одной буквой 6 в конце вхождение подобного же образца из М вЂ” 1 букв а также с одной буквой 6 на конце потребует максимального количества сравнений. Однако, усовершенствованные методы способны существенно улучи>ить поиск в таких неблагоприятных случаях.
6.1.5 Алгоритм Кнута-Мориса-Пратта В 1977 г<>ду Д. Кнут, Д. Морис и В. Пратт изобрели алгоритм, фактически требующий только Х сравнений даже в самом плохом случае вместо Х ЛХ. Новый алгоритм основывается па том соображении, что, начиная каждый раз сравнение образца с самого начала, мы действуем вслепую и забываем ценную информацию о неудачном поиске. После частичного совпадения начальной части образца с соответствуюгцими литерами последовательности мы фактически знаем удачно пройденную 1совпавшую1) часть строки и можем вычислить некоторые сведения на основе самого образца (и только нсто1), с помощью которых потом быстро продвинемся по тексту, если прсфиксно-периодичсская структура, образца делает заведомо неуспешными ближайшие сравнения контекста поиска.
Как же можно осветить сканируемун> последовательность для более оыстрого и дальнего продвижения после неудачи! Для иллюстрации идеи алгоритма приведем пример поиска. слова «Ноо11яап». Знаки, подвергшиеся сравненин>, подчеркнуты. При каждом несовпадении двух знаков образец сдвигается по последовательности вперед на все пройденное расстояние, поскольку при анализе образца установлено, что меньшие гдвиги не могут привести к полному совпадению.
Ноо1а-Ноо1а Нтг1в 111се Ноо11Напв. Ноо11Нап Ноо11Нап Ноо11Нап Ноо11яап Ноо11Нап Ноо11Нап Псевдокод КМП-алгоритма в терминах нредиката частичного совпадения с образцом Р и предиката первого вхождения с г записывается так: О; 1' Индекс ока>гирования, последоватальнг>стаи ~ О: 1' Индекс сравне>гия г образце.
>Г 1' Образец не иго рпан«и строка не зокопчилась >Г игЬ11е(1 < М) апс1 (1 < Х) с1о Ьеп1п 1г Истпи>сна конвюнкг1ин С~(1 — 1) ьг Р(г — 1, 1) >г 1' г заменено на г — >, т. к. ковда была начата попьипка сопоставления с образцом у' букв тому назад, полного совпадения на этом отрезке не бгыло, а частичное совпадение имеет место, т. е. условие применяется к подстроке., начинаюсцейся ранее, в силу ее частичного совпадения с образцом , и первый аргумент, врсдикатов смесцается назад к нпчалу участка совпадения,. >~ лчЫ1е(> > - О) апс1 (в[Ц <> ри) с1о Е' Х: — — В(Х) прызюок опересЭ, ХЭ(1) — некая фуикция ска">кообразнг>го смеи1ения по гаравтирос>ан»о перелевпнтпому контексту >> 1; Х Эволюционное дви>юепие.
по строке с мипим>ал>ьвым и>агом >> 3: 3 епс1; Фуллкция с>п>ига В будет нами установлена позднее, а сейчас займемся обоснованием вложенного цикла поиска. Условия С,?(> — 1) и Р(> — Х, Х) являются глобальными инвариантами циклов так же, как и отношения О < > < >У и О < Э < М. ЕЕапомним, что ф> — 1) есть условие первого вхождения > букв тому назад относительно текущего индекса сканирования Х, а Р(> — Э, Э) — — предикат частичного совпадения первых Х букв образца, начиная с 1 — > буквы последовательности. Это позволяет нахл отказаться от слежения за текущим указателем > первой литеры образца в последовательности и перейти к относитсл>»ему положению образца > — 1 в этой последовательности. Е'.ели алгоритм заканчивает рабс>ту по исчерпани>о образца > = ЛХ, то составляющая прсдусловия внешнего цикла Р(> — 1, >) обратится в Р(> — М, ЛХ), т.
е. по определению предиката частичного совпадения Р оно начинается с позиции > — ЛХ. Если же выполнение закончено по концу последовательности из-за 1 = >у, то, поскольку при этом Х < Л1, .из инварианта ~(>) следует,что совпадения вообще нет. теперь надо доказат>ь что алгоритм делал".т то, лто надо, т. е. никогда не нару>пает инварианта. ОЕегко видеть, что вначале 1 = > = О и инвариант истинсн.
Сначала исследуем эффект от двух операторов, сл>>>агро>>но увсличивак>щих Е и 1 на единицу. Они., очевидно, не сдвигают образец вправо по строке и не делают ложным С.,>(>' — 1), поскольку разность остается неизменной. Но, может быть, они делают ложным Р(1 — Х, 1) - вторую коньк>нктивнун> составляющую инварианта'? Обращаем внимание, что по определснллю цикла лл>Ел11е в этой точке истинно отрицание выражения в заголовке внутреннего цикла, т. с.
либо > < О, либо з, = р>. Последнее условие увеличивает частичнос совпадение и устанавливает истинность Р(> — Э, 1+ 1), а первое - постулирует (свидетельствует об) истинность Р(> — Э, 1+ 1). Следовательно, одновременная единичная инкрементация > и Э не нарушает ни тот, пи другой инвариант. Осталось главное -- доказать, что Х;= В(Э) также сохраняет истинность инварианта. Надеясь отыскать такое семимильное и адекватное В, примем пока это на веру.. с1тобы составить функцию вычисления В мы должны сначала понять смысл осуществляемого ею действия.
11ри условии, что В < 1, присваивание соответствует сдвигу образца вправо на Э вЂ” В ллозиций (Х > В!). с1тобы сдвиг был настолько большим, насколько это возможно, В должно быть как можно меньше. В частности, В = — 1 означает максимальный сдвиг на весь образец. Если инвариант Р(> — Э, >) й Я(> — >) гюсле присвоения 1 значения В истиш>ен, то перед ним должно быть >лстинно 1>(л — В, В) й О(л — ЕЭ). Это предусловие и будет ориентиром при поиске подходящего выражения для В. Оснсл>ное соображение: благодаря истинности Р(>, — >,1) мы знаем, что "'-> = ро р>->, 315 то есть было частичное совпадение с образцом 1 букв тому назад относительно текущего указателя сканирования г. Поэтому условие частичного совпадения образца и фрагмента последовательности перед прыжком Р(г — В, О) с В ( у, развернутое в Ре.
Рп — ~ = ь"-и превращается в условие совпадения начала образца с его скачкообразной преодоленной частью Ро Рп-~ = РХ вЂ” и РХ вЂ” ~ и предикат — Р(г — й', М) для к = 1... ! — В превращается в Ро "Рь ~ ФР, ь РХ ~~~ =1",1 — ХХ, что подтверждает истинность одного из условий инварианта цикла. е,![г — В). Эти соотношения позволяют сделать важный вывод: значение 0 определяется только отыскиваемым образцом, точнее, его самоподобием (фрактальностью) и не зависит от сканируемой последовательности.
Кроме того, из этих условий следует, что для определения Г) мы должны для каждого смеьцения в образпе ! найти наименьшее Л, т. е. самую длинную последовательность литер образца, непосредственно предшествующих позиции 1, которая полностью совпадает с началом образца. Для каждого 1 такое В будем обозначать г! . Так как эти значения зависят только от образца,то перед началом поиска по какому-либо образну следует вычислить таблицу И, для этого образца, причем согласно вышеупомянутым соотношениям эти вычисления представляют собой ни что иное, как быстрое поисковое исследование самого образца этим же методом.
К тому же затраты на построение таблицы с! никак не болыпе ЛХ2. а размер образца ЛХ, конечно же, много меньше длины гюследовательности Л'. Поэтому однократное вычисление 4 (претрансляция образца [54]) не окажет заметного влияния на время поиска. Для повторного (и многократного!) поиска данного образца эту таблицу вычислять не потребуется. Конкретные примеры функции де Строка Образец 17 = 0 Присваивание у:= В сдвигает образец на ! — 0 позиций. Строка Образец Сдвинутый 1 = 5, 0 [5] = 4, (шах й~Ет =1 — с![]] = 1) р[О]...
р[З] = р[1]... Р[4] 316 Строка, Образец Сдвинутый 1 = 5, с3[5] = 2, 1пзах йй =1 — д[[] = 3) р[0]... р[Ц = р[3]... р[4] р[0] ... р[2] ф р[2] ... р[4] р[0] ... р[3] ф р[Ц ... р[4] Строка Образец Сдвинутый 1 = 5. 0 [5] = О, (тах йй =1 — й[[] = 5) р[О] ... р[О] ~ р[4] ... р[4] р[0] ... р[Ц ф р[З] ... р[4] р[О]... р Р] ~ р[г]...
р[4] р[0]... р[3] ф р[Ц... р[4] Частичное совпадение с образцом и вычисление д Строка Образеи, ~ двинутый 1 = 5, 0[5] = — 1, (а1нй =1 — д[]] = б) Строка Образец Сдвинутый 1 = 5,. 0[5] = — 1, .(й~й = 1' — 0 [1] = б) Образец сдвигается за его последнюю литеру 11оследний пример на предыдущем рисунке наводит на, мысль увеличения сдвига: так как р равно А вместо У'", то соответствующая литера последовательности нс может быть Л из-за того, что условие а, ф р заканчивает цикл.
Следовательно, сдвиг на 5 не приведет к последующему совпадению, и поэтому можно увеличить сдвиг до шести. Учитывая это, мы переопределим вычисление д. как поиск самой длинной совпадаюсаей последовательности в самом образце РО Рз,-1 Ф Р,-зз Р,-1 с дополнительным ограничением рзг ф р . Если никаких совпадений нет, то мы считаем И = — 1, что дает сдвиг аж па целый образец относительно его текущей позиции (рис. 1.12, внизу).
Ясно, что вычислоние И само представляет собой поиск в строке и мы для этого тоже можем использовать сам КМП-алгоритм. Первая часть предлагаемой программы КМР как раз и содержит такое самоприменение КМ11-алгоритма к вводимому образцу. Далее, после построения таблицы, осуществляется быстрый поиск образца в ранее введенной последовательности. Как всегда, ускорение поиска обусловлено сокращением перебора и неуда сных попыток сопоставлсния с образцом путем больших сдвигов на дальние расстояния, величина которых гарантирована по построению таблицы И:.
ргоигаш КМР(1прпС, опьрпс~; сопвС Мигах -- 100; Мп1ах — 10000; айаг 1, 1, .1с, 1сО, М, Х: шСеиег; с: сЬаг: р: аггау [О..Мп1ах — 1[ оГ сЬаг; 1' Образец для поиска 3 з: аггау [0..1зшах — 1[ оГ сЬаг: 1' Последовагпсльность ~ с1: аггау [О..Мшах — 1] оГшСеиег: 1' Таблица сдвигов 1 Ьеи1п Х: 0:, ъкЬ11е поС ео1п с1о Ьеиш 1' Чтение последовательности ~ геас1(с); з [1э'1: — с; Х:: —:э —, 1; епс1: геас11п; лкЬ11е поС ео1 с1о Ьеи1п 1' Поиск, в поаледовате.льности з всех образцов, заданних в файле 1приС 3 гереаС 1' Чтение образца...