Рубрики
Без рубрики

Алгоритмический глубокий погружение: динамическое сопоставление строки

Настройка Рассмотрим минималистичный и строгий печатный игрок, в которой игрок должен ввести … Теги с алгоритмами, учебным пособием, Python, структурами данных.

Настраивать

Рассмотрим минималистичную и строгую игру в печатании, в которой игрок должен ввести кучу слов, появляющихся на экране до истечения таймера.

Что-то вроде этого:

Вся реализация игры является здесь

Хорошо! Давайте доберемся до этого тогда.

Проблема

Давайте рассмотрим проблему на самом деле Соответствие Строка игрока к списку слов. Типичная реализация его будет работать что-то подобное:

  • Запишите ввод игрока, мы будем ссылаться на свое настоящее состояние как Player_String
  • Когда игрок попадает в ввод, сопоставьте текущую строку проигрывателя со списком слов, как
if player_string in word_list:
    # do something

Сложность времени это O (Len (Player_String) * Len (Word_List)) , который в порядке, если мы обрабатываем только такое совпадение, когда игрок попадает в ввод. Но скажем, мы не хотим, что мы хотим, есть всякий раз, когда игрок нажимает любой ключ, Player_String соответствует словам в Word_List. Теперь более ранняя сложность времени кажется посторонним, и мы постараемся прийти с более элегантным и эффективным подходом для решения этого.

Требования

Перед тем, как идти в Nitty-Gritty от разных подходов, используйте паузу и перечислите наши точные требования.

  1. Соответствие строке необходимо сделать с каждым нажатием нажатия клавиши, а не только при попадании плеера.
  2. Мы должны поддерживать следующие действия пользователей:
    • Игрок может вставить буквенно-цифровой символ.
    • Игрок может удалить символ слева от положения курсора, если таковой, нажав backspace.
    • Игрок может перемещать положение курсора, используя клавиши направления влево.

Три подход

Если вы не знакомы с Три Структура данных, обратитесь здесь1 , здесь2 Отказ Очень кратко, Три Или префикс дерево – это структура данных, которая хранит список строк в древовидной структуре и помогает поддерживать временную сложность многих операций, таких как вставка, удаление и поиск на заказ O (Лен (слово)) . Примечание Три Может использоваться в различных контекстах, отличных от просто строк, см. здесь3 Чтобы понять, как пытается можно использовать для решения Битовое манипуляция вопросов.

Теперь, когда у нас есть внедрение, давайте посмотрим, как Пытается имеют отношение к нашей проблеме. Пытается на нас двумя способами:

  1. Храните список слов:

Что-то вроде Время, необходимое для хранения всех слов в списке, будет на заказ O (n * m) , где (слова) и (Лен (слово))

  1. Проверьте, если Player_String Соответствует любому слову:

Теперь, если вы следуете, эта часть довольно тривиальная. Мы начинаем у корня дерева, и для каждого персонажа ввели мы, пересекаем дерево соответственно, и если мы когда-нибудь приедем на узел с Последнее Уила! Есть матч, и мы можем ударить это слово из списка, простой кресть.

Но что произойдет, если игрок нажимает Backspace Наша структура данных по-прежнему не имеет возможности для обработки этого пользователя. Типичный Три Реализация не поддерживает возвращение по пути, но его можно легко добавить либо добавление дополнительного атрибута родитель каждому Три Узел Таким образом, мы можем вернуть обратно на один узел всякий раз, когда пользователь нажимает на задний план или так, как я сделал это, увеличив список, чтобы отслеживать все узлы, которые мы посетили при прохождении некоторых входных данных, а затем появляются узлы из этого списка с каждым задним пространством. Это увеличивает пространственную сложность для O (Лен (слово)) Но держит время сложности для O (1) Для введения и действий пользователя Backspace.

Реализация для этого Три На основе подхода можно найти здесь

Rolling Hash + Дейковый подход

Проблема с Три Основанный подход заключается в том, что, по крайней мере, к лучшему из моих знаний, нет способа включить действия по перемещению курсора. Подумайте об этом, это имеет смысл, Три Или префикс дерево, является структурой данных, которая предназначена для обработки, не сюрпризов здесь, префиксы И как только игрок начинает двигать его/ее курсор и начать печатать из произвольных позиций в строке, которую нарушено предпосылку. Так что же нам делать?

Rolling Hash приходит к спасению. Rolling Hash – это метод хеширования, которая обрабатывает один символ во время вычисления хеш-значение и в зависимости от того, как его реализует, может эффективно воспроизводить значения хеша, если некоторые символы (ы) должны вставлять/удалить. Rolling Hash используется в Рабин Карп Алгоритм для сопоставления шаблона здесь1. а также запросы на основе палиндром здесь2. .

Rolling Hash Интуитивно соответствует законопроекту, так как он позволяет нам эффективно вычислить хеш-значения для операций введения и удаления. Но как насчет курсора движущихся действий? Ну, потому что мы должны использовать Декес динамически поддерживать символы справа и слева от положения курсора. Этот подход работает таким образом:

  1. Храните список слов:

Мы вычисляем HASH Value для всех слов в списке и хранить их в словаре.

  1. Проверьте, если Player_String Соответствует любому слову:

Мы динамически вычисляем хеш-ценность Player_String С каждым действием пользователей и проверьте, присутствует ли значение HASH в словаре сохраненных хэшей, если да, то мы гарантируем, что строки на самом деле совпадают с помощью строки Brute-Force The Player_String с потенциальным совпадением.

Этот подход поддерживает временную сложность O (журнал (мод)) на действие пользователя, где мод Используется модуль при расчете хеш-значений строк. Обратите внимание, что этот подход зависит от уникальности алгоритма хеширования и используемого ключей. Для этого я использовал модуль ближе к ~ 10 ^ 10.

Реализация этого прокатаного хэш + подход к делу можно найти здесь

Так что это, то Rolling Hash + DECE Подход поддерживает минимальную срок сложности для нашей проблемы, поддерживая все предполагаемые пользовательские действия.

Я пытался кратко объяснить подходы и их необходимые очки, и поэтому они не могут быть на 100% всеобъемлющими, но посмотрите на код, я считаю, что будет очистить много путаницы. Плюс комментирует, если вы верите, что что-то не так ,наче или вы думаете, что есть более элегантный или эффективный способ решения этого, я хотел бы узнать об этом.

Оригинал: “https://dev.to/anirudd/algorithmic-deep-dive-dynamic-string-matching-430h”