Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

A b a c a b a b

A b a c a b a a b a b a b a c a b a b b

0 0 1 0 1 2 3 2

A b a c a b a b

Ниже представлена последовательность сдвигов. Слева показана разность j - f(j), определяющая величину сдвига, а справа – позиция образца, с которой будет продолжено последующее сравнение с текстом

7-3=4 a b a c a b a b позиция 4

3-1=2 a b a c a b a b позиция 2

1-0=1 a b a c a b a b позиция 1

3-1=2 a b a c a b a b позиция 2

3-1=2 a b a c a b a b позиция 2

Представим образец массивом символов P, функцию возвратов целочисленным массивом F и опишем ее вычисления в следующем фрагменте программы:

 

k:=0;

F[1]:=0;

For i:=2 to M do

begin

While (k>0) and (P[i]<>P[k+1]) do k:=F[k];

if P[i]=P[k+1] then k:=k+1;

F[i]:=k;

end;

 

Обозначим через w (i) количество выполнений тела цикла While при i = 2, 3,…, M. Каждое выполнений тела цикла While уменьшает значение k не меньше, чем на 1. Отсюда

F[i] ≤ F[i-1] – w (i) +1, то есть w ( i ) ≤ F[i-1] – F[i] + 1

Тогда после суммирования w (2) + w (3) +…+ w (M) ≤ M – 1. Общая трудоемкость построения функции возвратов составляет O(M).

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

 

Program SubString;

Var

P: array[1..255] of char;

F: array[1..255] of integer;

C: char; {очередной символ текста}

pp: integer; {текущая позиция в образце}

tp: integer; {текущая позиция в тексте}

Fin, Fout: text; {входной и выходной файлы}

Begin

{ввод образца, построение массива F:

значений функции возвратов}

pp:=0;

tp:=0;

While not eof(Fin) do

Begin

tp:=tp+1;

Read(Fin,C); {очередной символ текста}

While (pp>0) and (P[pp+1]<>C) do

pp:=F[pp]; {следующее ‘начало-конец’}

if P[pp+1]=C then pp:=pp+1;

if pp = M then {совпал последний символ образца}

begin

Write(Fout,tp-M+1,' ');

{позиция первого символа}

pp:=F[pp];

{подготовка к поиску следующего вхождения}

end;

End;

End.

 

Оценим количество сравнений символов. На каждом шаге внешнего цикла tp увеличивается на 1, а pp увеличивается на 1, а иногда уменьшается как минимум на 1 за счет присваивания F[pp]. Обозначим через b (tp) начальное значение pp при очередном значении tp, а через w (tp) – количество уменьшений pp при одной и той же позиции tp в тексте. Тогда b (tp) ≤ b (tp -1) – w (tp)+1 при tp >1 или w (tp) ≤ b (tp -1) - b (tp)+1. Отсюда вычисление суммы значений w (i) имеет трудоемкость порядка N. Поскольку tp увеличивается N -1 раз, то общая трудоемкость алгоритма с учетом вычисления функции возвратов составляет O (M+N).

Алгоритм КМП обеспечивает во всех случаях линейную сложность, но не является самым эффективным алгоритмом.

Алгоритм БойераМура [19] имеет нелинейную оценку трудоемкости в худшем случае, но в среднем работает быстрее. Здесь можно провести аналогию с широко известным алгоритмом быстрой сортировки Хоара [1, 3, 5, 7, 11], который имеет квадратичную трудоемкость на специально подобранных данных. Этот алгоритм считается наиболее быстрым среди алгоритмов общего назначения, предназначенных для поиска подстроки в строке.

Простейший вариант алгоритма Бойера-Мура состоит из следующих шагов. На первом шаге мы строим таблицу смещений для искомого образца. Процесс построения таблицы будет описан ниже. Далее мы совмещаем начала строки и образца и начинаем проверку с последнего символа образца. Если последний символ образца и соответствующий ему при наложении символ строки не совпадают, образец сдвигается относительно строки на величину, полученную из таблицы смещений, и снова проводится сравнение, начиная с последнего символа образца. Если же символы совпадают, производится сравнение предпоследнего символа образца и т. д. При несовпадении очередного символа величина сдвига определяется выражением L - K, где L – значение из таблицы смещений, а K – количество совпавших символов. После сдвига снова начинаем проверку с последнего символа.

Если все символы образца совпали с наложенными символами строки, значит, мы нашли подстроку. Если одной подстроки достаточно, то поиск окончен. Иначе сдвигаем образец либо на его длину в том случае, когда находимые подстроки не должны пересекаться, либо на один символ.

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

Величина смещения для каждого символа образца зависит только от порядка символов в образце, поэтому смещения удобно вычислить заранее и хранить в виде одномерного массива, где каждому символу алфавита соответствует смещение относительно последнего символа образца. Если символ отсутствует в образце, то заносится значение M.

Поясним все вышесказанное на простом примере. Пусть у нас есть алфавит из пяти символов: a, b, c, d, e и мы хотим найти вхождение образца abaad в строке abecdacbbdbabaad. Длина образца M = 5. Таблица смещений будет выглядеть так:

<== предыдущая лекция | следующая лекция ==>
A b a c a b a с a b c a b a c a b a b b | A b a a d
Поделиться с друзьями:


Дата добавления: 2014-01-11; Просмотров: 339; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




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