Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы и структуры данных.doc
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
1.14 Mб
Скачать

3.1Поиск в строке

Задача поиска слова (подстроки) в строке сводится к поиску индекса элемента i в строке S, такого что

1 <= i <= (n-1)

и, начиная с индекса i, имеет место посимвольное совпадение всех элементов строки P с последовательно расположенными символами строки S. Иными словами, для

j = 0  m-1

имеет место равенство

S[i+j] = P[j+1],

а задача является решенной, если, начиная с некоторого значения индекса i, обеспечивается истинность m попарных сравнений соответствующих элементов строк S и P. Тогда задача сводится к проверке истинности предиката Find (i, m).

Пример. Пусть строка S имеет вид:

высокопроизводительная система обработки информации

Пусть слово P – имеет вид

обработки

Тогда при i = 32 получим Find (i, m) = true.

Суть задачи поиска слова (подстроки) в строке иллюстрируется следующим фрагментом программы. Задача сводится к выполнению повторяющейся проверки истинности предиката Find (i, m).

var Found: Boolean;

S: string;

P: string;

N: integer; {размер исходной строки}

M: integer; {размер искомой подстроки}

I: integer;

begin

{Ввод строки (массива) S}

{Ввод строки (массива) P}

N := Length (S);

M := Length (P);

I := 0;

repeat

I := I + 1; {поиск начинается с элемента S[1] из-за особенности представления строк в Pascal}

Found := Find (I, M);

until Found or (I = N – M);

end;

Условием окончания поиска является истинность предиката Find (I, M) или наступление момента, когда в строке S останется меньше чем m нерассмотренных элементов.

3.2Простой поиск в строке

Ниже приводится полный алгоритм поиска. В нем, фактически, раскрыто содержание предиката Find (I, M).

procedure FindSubString (S: string; P: string; var Position: integer;

var Find: Boolean);

var I, J: integer;

N: integer; {размер исходной строки}

M: integer; {размер искомой подстроки}

begin

N := Length (S);

M := Length (P);

I := 0;

Find := false;

repeat

I := I + 1;

{Начало реализации предиката Find (i, m). Сравнение начинается с элементов S[1] и P[1] из-за особенности представления строк в Pascal}

J := 0;

while (J<M) and (S[I + J] = P[J+1]) do

J := J + 1;

{Конец реализации предиката Find (i, m)}

until (J = M) or (I = N – M);

if J <> M then Exit; {подстрока не входит в строку}

Position := I – J; {позиция начала подстроки в строке}

Find := true; {устанавливается истинность признака "подстрока входит в строку"}

end; {FindSubString}

Условием окончания поиска (аналог Found = true) является истинность условия (j = m).

Приведенный выше алгоритм работает достаточно хорошо независимо от длины слова (подстроки) поиска, если несовпадение обнаруживается после небольшого в пределах 2 –3 сравнений. Чаще всего так и происходит (см. приведенный выше пример), особенно для традиционных текстов – книги, статьи и т.д.

Так в рассматриваемом примере каждое очередное несовпадение обнаруживается после одного сравнения. А общее количество сравнений составило 40 = 31 + 9. Из них 31 – количество сравнений до начала совпадения с образом, и 9 – количество сравнений, определяемых длиной образа.

Однако в ряде более специфических текстов, содержащих большое количество следующих подряд одинаковых символов, например, ААААААААААААААБББ и т.д., алгоритм непроизводителен. В таких случаях требуется до n*m сравнений.

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