Skip to content

Latest commit

 

History

History
51 lines (43 loc) · 5.66 KB

Hash.md

File metadata and controls

51 lines (43 loc) · 5.66 KB

Домашнее задание к занятию 6. Хеширование

Инструкция по выполнению домашнего задания:

1. Зарегистрируйтесь на сайте repl.it;
2. Перейдите в раздел my repls;
3. Нажмите кнопку Start coding now! - если вы приступаете впервые, или New Repl - если у вас уже есть работы;
4. В списке языков выберите тот язык, который изучаете;
5. Код пишите в левой части окна - в редакторе кода;
6. Чтобы посмотреть результат выполнения файла, нажмите на кнопку Run. Результат появится в правой части окна;
7. После окончания работы скопируйте ссылку на ваш repl в адресной строке браузера;
8. Скопированную ссылку (ваше решение ДЗ) нужно отправить на проверку. Для этого перейдите в личный кабинет на сайте netology.ru, в поле комментария к домашней работе вставьте скопированную ссылку и отправьте работу на проверку;


Рабин-Карп с шаблонами

Давайте применим упрощённый алгоритм Рабина-Карпа для поиска подстроки в строке, но теперь в шаблоне будет один спец-символ *, который будет означать, что подойдёт любая буква.

Давайте рассмотрим на примере. Строка, в которой будем искать: Alibaba or Alibubab? I do not know!. В качестве шаблона возьмём b*b. Есть три подстроки, который подойдёт под этот шаблон: bab (начинается на позиции 3), bub (начинается на позиции 14) и второй bab (начинается на позиции 16).

Давайте для этого модифицируем алгоритм Рабина-Карпа. Мы всё ещё будем использовать упрощённую версию, где в качестве хеша считаем просто сумму кодов символов. В чём же будет состоять модификация? Вместо того чтобы считать хеш на всём шаблоне и сравнивать его с хешами на всех символов очередного кандидата на найденную подстроку, будем считать хеш на всём шаблоне без учёта символа *, а из хеша кандидата вычитать код символа, который стоит на позиции, соответствующей позиции * в шаблоне. Также при равенстве хешей мы будем проверять на ревенство все символы, пропуская позицию с *, тк в неё подойдёт любой символ текста.

Заметим, что тогда если есть подстрока, подходящая под шаблон, то хеш шаблона и хеш кандидата будут совпадать. Также, ничего нам не мешает всё также динамично поддерживать хеш кандидата, подсчитывая его из хеша предыдущего кандидата за O(1). Итоговая асимптотика будет такая же, как и у обычного Рабина-Карпа.

def search(source, pattern):
  if source короче pattern:
    return Такой подстроки точно нет!
  found = []
  pattern_hash = сумма кодов символов в pattern без учёта *
  asterik_position = позиция '*' в pattern
  for start от 0 до длина(source) - длина(pattern) + 1
    if start == 0:
      window_hash = сумма кодов первых длина(pattern) символов source
      window_hash -= код символа в source на позиции asterik_position
    else:
      window_hash -= код символа в source на позиции start-1
      window_hash += код символа в source на позиции start+длина(pattern) - 1
      window_hash += код символа в source на позиции где была '*' у прошлого кандидата
      window_hash -= код символа в source на позиции где стоит '*' у текущего кандидата
    if window_hash == pattern_hash:
      for i от 0 до длина(pattern):
        if pattern[i] != '*' И source[start + i] != pattern[i]:
          не подходит
      если подошёл, то добавим start в found
  return found

Реализация

  1. Напишите функцию поиска шаблона в строке по схеме, данной выше
  2. Проверьте её на примере выше, убедитесь что ответы совпали
  3. Загрузите ваше решение на сайт repl.it, отправьте ссылку на него на проверку.