Як було зазначено, ця проблема схожа на більш відому проблему відстані редагування (що лежить в основі відстані Левенштейна ). Він також має спільні риси, наприклад, з динамічною дистанцією викривлення часу (дублювання або "заїкання" у вашій останній вимозі).
Кроки до динамічного програмування
x=x1…xny=y1…ymd(x,y)
min⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪d(x,y1…ym−1)+1d(x,y2…ym)+1d(x,y1…ym/2)+1d(x1…xn/2,y)+1d(x1…xn,y)+1d(x1…xn−1,y1…ym−1)if y=y1…ym/2y1…ym/2if x=x1…xn/2x1…xn/2if yn=ym▻ Add letter at end▻ Add letter at beginning▻ Doubling▻ Halving▻ Deletion▻ Ignoring last elt.
Тут останній варіант в основному говорить про те, що перетворення FOOX в BARX еквівалентне перетворенню FOO в BAR. Це означає, що ви могли використовувати параметр «Додати літеру в кінці» для досягнення ефекту заїкання (дублювання) та видалення в точці. Проблема полягає в тому, що вона автоматично дозволяє додавати довільний символ в середині рядка , а , що - то ви , ймовірно , не хочете. (Це «ігнорування однакових останніх елементів» - це стандартний спосіб домогтися видалення та заїкання у довільних позиціях. Це забороняє довільні вставки, дозволяючи додавання в будь-якому кінці, хоч трохи складним, хоча…)
Я включив цю розбивку, навіть якщо вона не виконує цю роботу повністю, на випадок, якщо хтось може якось її "врятувати" - і тому, що я використовую її в своєму евристичному рішенні нижче.
(Звичайно, якщо ви могли отримати подібний розрив, який фактично визначив вашу відстань, вам потрібно буде лише додати пам ятку, і ви матимете рішення. Однак, оскільки ви не працюєте лише з префіксами, я не хочу ' не думаю, що ви можете використовувати просто індекси для запам'ятовування; можливо, вам доведеться зберігати фактичні, модифіковані рядки для кожного виклику, які вийдуть величезними, якщо ваші рядки значного розміру.)
Кроки до евристичного рішення
Інший підхід, який може бути простішим для розуміння, і який міг би використовувати трохи менше місця, - це пошук найкоротшого "редагування шляху" від першої рядки до другої, використовуючи алгоритм (в основному, найкращий- перша гілка). Простір пошуку буде визначено безпосередньо вашими операціями редагування. Тепер, для великої струни, ви бA∗отримати велике сусідство, оскільки ви можете видалити будь-який символ (надаючи вам сусіда для кожного потенційного видалення) або дублювати будь-який символ (знову ж, надаючи лінійну кількість сусідів), а також додавання будь-якого символу в будь-якому кінці, що б дасть вам кількість сусідів, що дорівнює подвоєному розміру алфавіту. (Просто сподіваюсь, що ви не використовуєте повний Unicode ;-) При такому великому вентиляторі ви можете досягти значного прискорення за допомогою двостороннього або якогось родичаA∗ .
Для того, щоб працював, вам знадобиться нижня межа для відстані до вашої мети. Я не впевнений, чи є очевидний вибір тут, але те, що ви можете зробити, це реалізувати динамічне рішення програмування, засноване на рекурсивному розкладі, яке я дав вище (знову ж таки з можливими проблемами з простором, якщо ваші рядки дуже довгі). Незважаючи на те , що розкладання неточно обчислити дистанцію, то це гарантовано буде нижньою межею (бо це більш поблажливими), що означає , що він буде працювати як евристика в . (Наскільки це буде щільно, я не знаю, але це було б правильно.) Звичайно, запам'ятовування вашої зв'язаної функції може бути спільним для всіх обчислень пов'язаних під час вашогоA∗A∗A∗бігати. (Проміжок часу / простір там.)
Тому…
Ефективність мого запропонованого рішення могла б трохи залежати від (1) довжини ваших рядків та (2) від розміру вашого алфавіту. Якщо жодне не є величезним, воно може спрацювати. Це:
- Реалізуйте нижню межу на відстані, використовуючи моє рекурсивне розкладання та динамічне програмування (наприклад, за допомогою запам’ятовуваної рекурсивної функції).
- Реалізуйте (або двонаправлений ) за допомогою операцій редагування як "переміщення" у просторі стану та нижню межу на основі динамічного програмування.A∗A∗
Я не можу реально дати жодних гарантій наскільки це було б ефективно, але це повинно бути правильним, і це, мабуть, буде набагато краще, ніж жорстоке рішення.
Якщо нічого іншого, я сподіваюся, що це дає вам деякі ідеї для подальших розслідувань.