· Получите вариант задания у преподавателя.
· Составьте алгоритм поиска элемента по заданному значению.
· Реализуйте алгоритм на языке Си таким образом, программа искала индексы всех имеющихся в массиве заданных элементов.
· Проанализируйте полученные результаты.
Организация поиска подстроки в строке
Цель работы
Ознакомиться и реализовать алгоритмы поиска подстроки в строке.
Последовательный (прямой) поиск
Алгоритм прямого поиска подстроки подобен алгоритму прямого поиска элемента с заданным значением в массиве.
Пусть T – текст, O – подстрока поиска. Длина текста равна m, длина подстроки n.
1. i = 0; // счетчик символов текста
2. ПОКА(i<m)
k = 0; // счетчик совпадений
j=0; // счетчик символов подстроки
i1 = i;
ПОКА(O[j]==T[i1]&& k<n && i1<m)
2.4.1. k++;
2.4.2. j++,i1++;
2.5. Конец цикла
2.6. ЕСЛИ (k==n) ТО вернуть i;// успех при поиске
2.7. i++;
3. Конец цикла
4. Вернуть -1. // неуспех при поиске
В худшем случае, время поиска в этом алгоритме прямо пропорционально n*(m-1).
Алгоритм поиска Кнута
Алгоритм, предложенный Кнутом для осуществления поиска, основан на анализе символов подстроки. В зависимости от вида подстроки и количества имеющихся совпадений алгоритм позволяет выполнить сдвиг по тексту более чем на один символ.
Вся основная работа проводится в начале алгоритма. Если в поиске участвует подстрока длины n, то может быть 0, 1, 2, 3, …, n-1 совпадений с текстом (как только произойдет n совпадений - подстрока найдена). Обозначим за j количество совпадений. Для дальнейшей работы рассчитаем элементы массива по следующему правилу:
длина максимальной подстроки до символа с номером j, полностью совпадающей с началом образа.
Значения и
постоянны и равны соответственно -1 и 0.
Сам сдвиг рассчитывается по формуле:
Рассмотрим на примере подстроки ААBCDAABD.
![]() | |
![]() | |
![]() | ААBCDAABD |
![]() | ААBCDAABD |
![]() | ААBCDAABD |
![]() | ААBCDAABD |
![]() | ААBCDAABD |
![]() | ААBCDAABD |
![]() | ААBCDAABD |
Предположим, что необходимо найти эту подстроку в тексте
A | A | B | D | A | A | B | C | A | A | B | C | D | A | A | B | D |
A | A | B | C | D | A | A | B | D | j=3, shift = 2 | |||||||
A | A | B | C | D | A | A | B | D | j=0, shift = 1 | |||||||
A | A | B | C | D | A | A | B | D | j=0, shift = 1 | |||||||
A | A | B | C | D | A | A | B | D | j=4, shift = 3 | |||||||
j=9, поиск окончен | A | A | B | C | D | A | A | B | D |
Поиск Боуера-Мура
Этот поиск начинает сравнивать подстроку со строкой, начиная с последнего символа подстроки. Пусть сравнение начинается с позиции i -1. Если нет полного совпадения, то сдвиг можно произвести на величину , где
- символ строки в позиции i-1. Сама величина сдвига определяется следующим образом:
- d равно длине образа, если символ не принадлежит подстроке;
- d равно расстоянию от самого правого в подстроке вхождения символа до ее конца.
Рассмотрим на примере подстроки «образ », подстрока ищется в тексте «отказ приказ город образ пример ». Аналогично поиску Кнута таблица сдвигов рассчитывается еще до работы алгоритма и для рассматриваемого примера равна:
![]() | ![]() | ![]() | ![]() | ![]() |
Все остальные символы алфавита имеют d равное 5 (длине образа).
о | т | к | а | з | п | р | и | к | а | з | г | о | р | о | д | … | ||
о | б | р | а | з | сдвиг на 5 позиций | |||||||||||||
о | б | р | а | з | сдвиг на 5 позиций | |||||||||||||
о | б | р | а | з | сдвиг на 4 поз. | |||||||||||||
о | б | р | а | з |
г | о | р | о | д | о | б | р | а | з | п | р | и | м | е | р | ||||
о | б | р | а | з | сдвиг на 5 позиций | ||||||||||||||
о | б | р | а | з | подстрока найдена |