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

Тақырыбы: Кнут-Морис- Пратта алгоритмін қолдану

Тапсырмалар:

1. Будем использовать этот алгоритм, чтобы выяс­нить, является ли слово X длины п полсловом слова Удойны т. (Как это делать с помощью специально­го разделителя #, описано выше.) При этом число действий будет не более С*(п +т), и используемая память тоже. Придумать, как обойтись памятью не более Сп (что может быть существенно меньше, если искомый образец короткий, а слово, в котором его ищут — длинное).

2. Написать соответствующий алгоритм (проверяю­щий, является ли слово Х = х[1]..х[п] полсловом сло­ва Y=y[1]..y[m]).

әдебиет:

1.Негізгі – 3, 5, 9-12

2. Қосымша - 4

Әдістемелік нұсқау:

К заданию №1 применяем алгоритм КМП к слову А#В. При этом вычисление значений l[1], ..., l[п] проводим для слова X дойны т и запоминаем эти значения. Дальше мы помним только значение l [i] для текущего i — кроме него и таблицы l[1]..l[n] нам доя вычислений ничего не нужно.

На практике слова X и Y могут не находиться под­ряд, поэтому просмотр слова Х и затем слова У удоб­но оформить в виде разных циклов. Это избавляет также от хлопот с разделителем.

По заданию №2. Сначала вычисляем таблицу l[1]..l[n], как делали раньше. Затем пишем такую программу:

j:=0; len:=0

{len - длина максимального начала слова X, одновременно являющегося концом слова y[l] …j[j]}

while (len<>n) and (j<>m) do

begin

while (x[len+l]<>y [ j + 1] ) and (len>0) do

begin

{начало оказалось неподходящим, применяем к нему n}

len :=1 [len] ;

end;

{нашли подходящее или убедились в отсутствии}

if х [len+1] =у [ j+1] do

begin {x [1] . .x [len] - самое длинное подходящее начало}

len:=len+l;

end

else begin {подходящих нет} len:=0; end;

end;

{если len=n, слово Х встретилось; иначе мы дошли до конца слова Y, так и не встретив X}

36 жұмыс

Тақырыбы: Поиск подстроки в строке

Тапсырмалар:

Заданы две строки s и х. Длина первой строки n, длина второй — m, причем 0<=m<=n. Требуется ответить на вопрос, является ли строка х подстрокой строки s, при этом поиск подстроки должен обнаруживать первое вхождение х в s.

Даны строка и подстрока. Составить программу, которая определяет вхождение подстроки в строку по алгоритму Бойера—Мура.

әдебиет:

1.Негізгі – 3, 5, 9-12

2. Қосымша - 4

Әдістемелік нұсқау:

Решение Тапсырмалар №1.

Самым простым методом поиска является метод прямого поиска. Рас­смотрим его на примере. Пусть s = «воротник», а х = «рот». Длина первой строки п = 8, длина второй — т = 3. В данном случае х является подстрокой s, следователь­но, надо найти такое значение индекса i, что для любого значения индекса k (1,,k,,3) будет выполняться равенство s[i+k] = x[k].

Начальное значение i равно 0.

1-й шаг: i= 0, k= 1 — сравниваем s[l] и х[1]: «в» «р», значит, с первой пози­ции вхождения нет, надо увеличить на 1 значение i.

2-й шаг: i= 1, k= 1 — сравниваем s[2] и х[1]: «о» «р», снова надо перейти к следующему i.

3-й шаг: i = 2, k=1 — сравниваем s[3] и х[1]: «р» = «р», следовательно, воз­можно совпадение, надо увеличить k.

4-й шаг: i = 2, k= 2 — s[4] = х[2] («о» = «о») — снова надо увеличить k.

5-й шаг: i = 2, k-3 — s[5]=x[3] («т» = «т») — полное совпадение! Далее поиск можно не продолжать, так как требовалось обнаружить лишь первое вхож­дение х в s.

Таким образом, прямой поиск подстроки в строке сводится к последовательным сравнениям отдельных символов. Поиск продолжается до тех пор, пока не обнару­жится вхождение (факт вхождения будем хранить в логической переменной f) или пока не будет пройдена вся строка 5. При этом можно закончить просмотр, когда i будет равно п — т, так как при следующих значениях i длина любого фрагмента строки s с позиции i меньше т.

Program Example;

Var s,x: String; ifj,n,m: Integer; f: Boolean;

Begin

Writeln('введите s, x');

Readln(s);

Readln(x);

n:=length (s);

m:=length (х); {определение длин строк}

i:=0;

f:=False; {признак того, что подстрока найдена}

Repeat

j:=1;

While (j<=m) And (s [i + j ] =x [j ] ) Do Inc(j);

If j=m+l Then f:=True Else Inc(i);

Until f Or (i>n-m);

If f Then Writeln(x,'является подстрокой',s,'с позиции-‘,I)

Else Writeln (x, 'не является подстрокой',s);

Readln;

End.

Этот алгоритм требует достаточно больших временных затрат, поскольку, ког­да п значительно больше m, число выполняемых сравнений — (п — т) т ~ пт.

Решение Тапсырмалар №2.

Поиск ведется от начала строки s, но с конца искомой подстроки х, для которой формируется таблица, размерность которой равна 256 (число всех возможных символов). Элементами таблицы являются расстояния от последнего символа искомой подстроки х до ее каждого символа. (Если в х встречаются одина­ковые символы, то в таблицу заносится расстояние до ближайшего из них.) Если символ в х не входит, то в соответствующую ячейку таблицы заносится т — длина подстроки х. Когда очередной символ подстроки не совпадает с очередным симво­лом строки s, для последнего из таблицы расстояний определяется соответствую­щее расстояние, после чего х сдвигается вправо на соответствующее число пози­ций. Тем самым ряд позиций пропускается, сокращая время поиска.

Program Example;

Var s,x: String; sd: Array[0..255] Of Integer;

Procedure search(s,x:String);

Var i,j,n,m: Integer; f: Boolean; h: Char;

Begin

n:=Length (s); m:=Length(x);{определение длин строки и подстроки; начальное заполнение массива расстояний}

For i:=0 To 255 Do sd[i]:=m;

For i:=1 To m-1 Do {заполнение массива расстояний}

Begin

h:=x[i]; sd[Ord(h)]:=m-i;

End;

i:=0; f:=False; {признак того, что подстрока найдена}

While (i<n-m+l) And (Not f) Do

Begin

j :=m;

While (j>0) And (s[i+j]=x[j]) Do j:=j-l;

If j=0 Then f:=True {полное совпадение!} Else i:=i+sd[0rd(s[i+j])]; End;

If f Then Writeln(x,'является подстрокой',s,'с позиции',i+1)

Else Writeln('нет вхождения.');

End;

Begin (Негізгі программа}

Writeln('Введите строку s.');

Readln(s);

Writeln('Введите подстроку х.');

Readln(x);

search (s,x);

Readln

End.

37 жұмыс