Лабы по АиСД 2023 / Baraeva_Elizaveta_lb4
.docМИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В. И. Ульянова (Ленина)
Кафедра МО ЭВМ
отчет
по лабораторной работе №4
по дисциплине «Алгоритмы и структуры данных»
Тема: Поиск образца в тексте. Алгоритм Рабина-Карпа
Студентка гр. 2383 |
|
Бараева Е. Н. |
Преподаватель |
|
Гаврилов А. В. |
Санкт-Петербург
2023
Цель работы.
Реализация и исследование алгоритма Карпа-Рабина для поиска образца в тексте, а также сравнение полученных результатов с теоретической оценкой.
Задание.
Напишите программу, которая ищет все вхождения строки Pattern в строку Text, используя алгоритм Карпа-Рабина.
На вход программе подается подстрока Pattern и текст Text. Необходимо вывести индексы вхождений строки Pattern в строку Text в возрастающем порядке, используя индексацию с нуля.
Примечание: в работе запрещено использовать библиотечные реализации алгоритмов и структур.
Ограничения
1 ≤ |Pattern| ≤ |Text| ≤ 5 · 105.
Суммарная длина всех вхождений образца в текста не превосходит 108. Обе строки содержат только буквы латинского алфавита.
Подсказки:
1. Будьте осторожны с операцией взятия подстроки — она может оказаться дорогой по времени и по памяти.
2. Храните степени x ** p в списке - тогда вам не придется вычислять их каждый раз заново.
Выполнение работы.
В начале определены две переменные d и mod, которые используются для вычисления хеша. Далее функция RabinKarp, которая принимает две строки pattern и text, возвращает список индексов, где найдено совпадение. Внутри функции происходит вычисление длины строк pattern и text и проверка на их соответствие. Если длина text меньше длины pattern или длина pattern равна нулю, то функция возвращает пустой список. Далее инициализируются переменные pattern_hash, text_hash, answer и h. Затем в цикле вычисляются хеши для pattern и text. После во внешнем цикле происходит сравнение хешей pattern и текущего подстроки text. Если они совпадают, то во внутреннем цикле происходит сравнение символов pattern и текущей подстроки text. Если они совпадают, то индекс текущей подстроки добавляется в список answer. После этого происходит обновление хеша text при переходе к следующей подстроке. Если значения text_hash становится отрицательным, то оно суммируется с mod. В конеце функция возвращает список answer. После функции происходит ввод пользователем в строки pattern и text, а затем вызывается функция RabinKarp с этими аргументами и результат выводится на экран.
Разработанный программный код см. в приложении А.
Тестирование.
Результаты тестирования представлены в табл. 1.
Таблица 1 – Результаты тестирования
№ п/п |
Входные данные |
Выходные данные |
Комментарии |
1. |
"text" "texttttttext"
|
[0, 8] |
Верно. |
2. |
"text" "tetextttr5656ttttextex334teeeet2ttxtextxxtexttext" |
[2, 16, 35, 41, 45] |
Верно. |
3. |
"" "" |
[] |
Верно. |
Вывод.
Был создан алгоритм Рабина-Карпа для поиска подстроки в тексте. Он использует хеширование, что является его главным отличием. Ключевыми факторами успеха этого алгоритма являются низкая вероятность коллизий и возможность эффективно вычислять хеш-значение последовательных подстрок. Результаты тестирования алгоритма показали его эффективность поиска на текстах со значительным объемом слов.
ПРИЛОЖЕНИЕ А ИСХОДНЫЙ КОД ПРОГРАММЫ
Название файла: main.py
d = 2 ** 11 - 1
mod = 2 ** 31 - 1
def RabinKarp(pattern: str, text: str) -> list:
length_text, length_pattern = len(text), len(pattern)
if length_text < length_pattern or length_pattern == 0:
return []
pattern_hash = 0
text_hash = 0
answer = []
h = pow(d, length_pattern - 1, mod)
for i in range(length_pattern):
pattern_hash = (d * pattern_hash + ord(pattern[i])) % mod
text_hash = (d * text_hash + ord(text[i])) % mod
for i in range(length_text - length_pattern + 1):
if pattern_hash == text_hash:
for j in range(length_pattern):
if text[i + j] != pattern[j]:
break
else:
answer.append(i)
if i < length_text - length_pattern:
text_hash = (d * (text_hash - ord(text[i]) * h) + ord(text[i + length_pattern])) % mod
if text_hash < 0:
text_hash = text_hash + mod
return answer
pattern = input()
text = input()
print(*RabinKarp(pattern, text))
Название файла: test.py
import main
def test_middle():
text = "texttttttext"
pattern = "text"
assert (main.RabinKarp(pattern, text) == [0, 8])
def test_big():
text = "tetextttr5656ttttextex334teeeet2ttxtextxxtexttext"
pattern = "text"
assert (main.RabinKarp(pattern, text) == [2, 16, 35, 41, 45])
def test_small():
text = "1t"
pattern = "t"
assert (main.RabinKarp(pattern, text) == [1])
def test_none():
text = ""
pattern = ""
assert (main.RabinKarp(pattern, text) == [])
