русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Алгоритм Боуера и Мура


Дата добавления: 2013-12-23; просмотров: 1668; Нарушение авторских прав


Пример программы

Program KMP;

const

Mmax = 100; Nmax = 10000;

var

i, j, k, M, N: integer;

p: array[0..Mmax-1] of char; {слово}

s: array[0..Mmax-1] of char; {текст}

d: array[0..Mmax-1] of integer;

begin

{Ввод текста s и слова p}

Write('N:'); Readln(N);

Write('s:'); Readln(s);

Write('M:'); Readln(M);

Write('p:'); Readln(p);

{Заполнение массива d}

j:=0; k:=-1; d[0]:=-1;

while j<(M-1) do begin

while(k>=0) and (p[j]<>p[k]) do k:=d[k];

j:=j+1; k:=k+1;

if p[j]=p[k] then

d[j]:=d[k]

else

d[j]:=k;

end;

{Поиск слова p в тексте s}

i:=0; j:=0;

while (j<M) and (i<N) do begin

while (j>=0) and (s[i]<>p[j]) do j:=d[j]; {Сдвиг слова}

i:=i+1; j:=j+1;

end;

{Вывод результата поиска}

if j=M then Writeln('Yes') {найден }

else Writeln('No'); {не найден}

Readln;

end.

 

Точный анализ КМП - поиска, как и сам его алгоритм, весьма сложен. Его изобретатели доказывают, что требуется порядка M+N сравнений символов, что значительно лучше, чем M*N сравнений из прямого поиска. Они так же отмечают то положительное свойство, что указатель сканирования i никогда не возвращается назад, в то время как при прямом поиске после несовпадения просмотр всегда начинается с первого символа слова и поэтому может включать символы, которые ранее уже просматривались. Это может привести к негативным последствиям, если текст читается из вторичной памяти, ведь в этом случае возврат обходится дорого. Даже при буферизованном вводе может встретиться столь большое слово, что возврат превысит емкость буфера.

Анализ КМП - поиска.Точный анализ КМП-поиска, как и сам его алгоритм, весьма сложен.

Его изобретатели до­казывают, что требуется порядка М + N сравнений символов, что значительно лучше, чем М * N сравнений из прямого поиска.



Они также отмечают то приятное свойство, что указатель сканирова­ния i никогда не возвращается назад, в то время как при прямом поиске после несовпадения просмотр всегда начинается с перво­го символа образа и поэтому может включать символы, которые ранее уже просматривались. Это может привести к неприятным затруднениям, если строка читается из вторичной памяти, ведь в этом случае возврат обходится дорого. Даже при буферизован­ном вводе может встретиться столь большой образ, что возврат превысит емкость буфера.

КМП-поиск дает подлинный выигрыш только тогда, когда неудаче предшествовало некоторое число совпадений. Лишь в этом случае слово сдвигается более чем на единицу. К несчастью, это скорее исключение, чем правило: совпадения встречаются значительно реже, чем несовпадения. Поэтому выигрыш от использования КМП-стратегии в большинстве случаев поиска в обычных текстах весьма незначителен. Метод же, предложенный Р. Боуером и Д. Муром в 1975 г., не только улучшает обработку самого плохого случая, но дает выигрыш в промежуточных ситуациях.

БМ-поиск основывается на необычном соображении √ сравнение символов начинается с конца слова, а не с начала. Как и в случае КМП-поиска, слово перед фактическим поиском трансформируется в некоторую таблицу. Пусть для каждого символа x из алфавита величина dx √ расстояние от самого правого в слове вхождения x до правого конца слова. Представим себе, что обнаружено расхождение между словом и текстом. В этом случае слово сразу же можно сдвинуть вправо на dpM-1 позиций, т.е. на число позиций, скорее всего большее единицы. Если несовпадающий символ текста в слове вообще не встречается, то сдвиг становится даже больше, а именно сдвигать можно на длину всего слова. Вот пример, иллюстрирующий этот процесс:

Ниже приводится программа с упрощенной стратегией Боуера-Мура, построенная так же, как и предыдущая программа с КМП-алгоритмом. Обратите внимание на такую деталь: во внутреннем цикле используется цикл с repeat, где перед сравнением s и p увеличиваются значения k и j. Это позволяет исключить в индексных выражениях составляющую -1.

 

Program BM;

const

Mmax = 100; Nmax = 10000;

var

i, j, k, M, N: integer;

ch: char;

p: array[0..Mmax-1] of char; {слово}

s: array[0..Nmax-1] of char; {текст}

d: array[' '..'z'] of integer;

begin

{Ввод текста s и слова p}

Write('N:'); Readln(N);

Write('s:'); Readln(s);

Write('M:'); Readln(M);

Write('p:'); Readln(p);

{Заполнение массива d}

for ch:=' ' to 'z' do d[ch]:=M;

for j:=0 to M-2 do d[p[j]]:=M-j-1;

{Поиск слова p в тексте s}

i:=M;

repeat

j:=M; k:=i;

repeat {Цикл сравнения символов }

k:=k-1; j:=j-1; {слова, начиная с правого.}

until (j<0) or (p[j]<>s[k]); {Выход, если сравнили все}

{слово или несовпадение. }

i:=i+d[s[i-1]]; {Сдвиг слова вправо }

until (j<0) or (i>N);

{Вывод результата поиска}

if j<0 then Writeln('Yes') {найден }

else Writeln('No'); {не найден}

Readln;

end.

 

Почти всегда, кроме специально построенных примеров, данный алгоритм требует значительно меньше N сравнений. В самых же благоприятных обстоятельствах, когда последний символ слова всегда попадает на несовпадающий символ текста, число сравнений равно N/M.

Авторы алгоритма приводят и несколько соображений по поводу дальнейших усовершенствований алгоритма. Одно из них √ объединить приведенную только что стратегию, обеспечивающую большие сдвиги в случае несовпадения, со стратегией Кнута, Морриса и Пратта, допускающей ⌠ощутимые■ сдвиги при обнаружении совпадения (частичного). Такой метод требует двух таблиц, получаемых при предтрансляции: d1 √ только что упомянутая таблица, а d2 √ таблица, соответствующая КМП-алгоритму. Из двух сдвигов выбирается больший, причем и тот и другой ⌠говорят■, что никакой меньший сдвиг не может привести к совпадению. Дальнейшее обсуждение этого предмета приводить не будем, поскольку дополнительное усложнение формирования таблиц и самого поиска, кажется, не оправдывает видимого выигрыша в производительности. Фактические дополнительные расходы будут высокими и неизвестно, приведут ли все эти ухищрения к выигрышу или проигрышу.

 



<== предыдущая лекция | следующая лекция ==>
Алгоритм кнута, Морриса и Пратта | Сортировка методом прямого включения


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.004 сек.