Відстань редагування (або Левенштейна) між двома рядками - це мінімальна кількість вставок, вилучень та підстановок з одним символом, необхідних для перетворення однієї рядки в іншу. Якщо два рядки мають довжину n кожна, добре відомо, що це можна зробити за O (n ^ 2) за допомогою динамічного програмування. Наступний код Python виконує цей обчислення для двох рядків s1
і s2
.
def edit_distance(s1, s2):
l1 = len(s1)
l2 = len(s2)
matrix = [range(l1 + 1)] * (l2 + 1)
for zz in range(l2 + 1):
matrix[zz] = range(zz,zz + l1 + 1)
for zz in range(0,l2):
for sz in range(0,l1):
if s1[sz] == s2[zz]:
matrix[zz+1][sz+1] = min(matrix[zz+1][sz] + 1, matrix[zz][sz+1] + 1, matrix[zz][sz])
else:
matrix[zz+1][sz+1] = min(matrix[zz+1][sz] + 1, matrix[zz][sz+1] + 1, matrix[zz][sz] + 1)
return matrix[l2][l1]
У цьому завданні ви повинні максимально наблизитись до обчислення відстані редагування, але з суворим обмеженням пам'яті. Ваш код може визначати один масив, що містить 1000 32-бітових цілих чисел, і це буде єдиним тимчасовим сховищем, яке ви використовуєте під час обчислення. Усі змінні та структури даних повинні міститись у цьому масиві. Зокрема, ви б не змогли реалізувати алгоритм, наведений вище, для рядків довжиною 1000, оскільки це вимагатиме від вас зберігання принаймні 1 000 000 номерів. Якщо у вашій мові звичайно немає 32-бітових цілих чисел (наприклад, Python), вам просто потрібно переконатися, що ви ніколи не зберігаєте в масиві число, більше 2 ^ 32-1.
Ви можете читати дані, використовуючи будь-яку стандартну бібліотеку на ваш вибір, не турбуючись про обмеження пам'яті в цій частині. Для того, щоб зробити конкуренцію справедливою для основної частини вашого коду, ви можете використовувати лише ті операції, які функціонально еквівалентні операціям на мові програмування С і не можуть використовувати жодні зовнішні бібліотеки.
Щоб бути надзвичайно зрозумілим, пам'ять для зберігання вхідних даних або використовується перекладачем вашої мови, JVM тощо не враховується до вашої межі, і ви можете нічого не записувати на диск. Ви повинні припустити, що вхідні дані доступні лише для читання, коли вони є в пам'яті, щоб не використовувати їх знову, щоб отримати більше робочого місця.
Що я маю реалізувати?
Ваш код повинен читатись у файлі у такому форматі. Він буде мати три лінії. Перший рядок - справжня відстань редагування. Другий - рядок 1, а третій - рядок 2. Я перевіряю його за допомогою зразків даних за адресою https://bpaste.net/show/6905001d52e8, де рядки мають довжину 10 000, але вони не повинні спеціалізуватися на цих даних. Він повинен вивести найменшу відстань редагування, яку він може знайти між двома рядками.
Вам також потрібно буде довести, що відстань редагування насправді відповідає дійсному набору змін. Ваш код повинен мати перемикач, який перетворює його в режим, який може використовувати більше пам'яті (скільки завгодно) і виводить операції редагування, які дають відстань для редагування.
Оцінка
Ваш рахунок буде найвищим (optimal edit distance/divided by the edit distance you find) * 100
. Щоб почати все, зауважте, що ви можете отримати оцінку, просто порахувавши кількість невідповідностей між двома рядками.
Ви можете використовувати будь-яку мову, яка вам подобається, вільно доступну та просту в установці в Linux.
Перерва на чай
У разі тай-брейку я запускаю ваш код на моїй машині Linux і виграє найшвидший код.
{ uint32_t foo[1000]; for (foo[0] = 0; foo[0] < 5; ++foo[0]) printf("%d ", foo[0]); }
Це передбачається, що ваш масив із 32-бітових цілих чисел буде викликаний foo
.
for(int i=0;i<=5;i++)
дозволено, оскільки він зберігає дані вi
?