Review the ru version with Codex. (#1870)

This commit is contained in:
Yudong Jin
2026-03-30 07:27:40 +08:00
committed by GitHub
parent 7a78369e4c
commit fe6443235b
97 changed files with 769 additions and 767 deletions
@@ -1,6 +1,6 @@
# Задача о расстоянии редактирования
Расстояние редактирования, также называемое расстоянием Левенштейна, обозначает минимальное число правок, необходимых для взаимного преобразования двух строк. Обычно оно используется для измерения сходства двух последовательностей в информационном поиске и обработке естественного языка.
Расстояние редактирования, также называемое расстоянием Левенштейна, - это минимальное количество изменений, необходимых для преобразования одной строки в другую. Обычно оно используется для измерения сходства двух последовательностей в информационном поиске и обработке естественного языка.
!!! question
@@ -12,7 +12,7 @@
![Пример данных для задачи о расстоянии редактирования](edit_distance_problem.assets/edit_distance_example.png)
**Задачу о расстоянии редактирования можно очень естественно описать через модель дерева решений**. Строки соответствуют узлам дерева, а один раунд решения (одна операция редактирования) соответствует одному ребру дерева.
**Задачу о расстоянии редактирования можно естественным образом объяснить с помощью модели дерева решений**. Строки соответствуют узлам дерева, а один шаг решения, то есть одна операция редактирования, соответствует одному ребру дерева.
Как показано на рисунке ниже, если не ограничивать число операций, то каждый узел может порождать множество ребер, и каждое из них соответствует одному из вариантов преобразования. Это означает, что преобразовать `hello` в `algo` можно множеством разных путей.
@@ -31,7 +31,7 @@
- Если $s[n-1]$ и $t[m-1]$ совпадают, их можно просто пропустить и сразу перейти к сравнению $s[n-2]$ и $t[m-2]$ .
- Если $s[n-1]$ и $t[m-1]$ различны, нужно выполнить над $s$ одну операцию редактирования (вставку, удаление или замену), чтобы последние символы стали одинаковыми, после чего можно перейти к задаче меньшего размера.
Иначе говоря, каждое решение (операция редактирования), которое мы выполняем над строкой $s$ , меняет те символы, которые еще остаются несопоставленными в строках $s$ и $t$ . Поэтому состояние определяется текущими позициями рассматриваемых символов в $s$ и $t$ , то есть состоянием $[i, j]$ .
Иначе говоря, каждый шаг решения, то есть операция редактирования над строкой $s$ , меняет те символы, которые еще необходимо сопоставить в строках $s$ и $t$ . Поэтому состояние определяется текущими позициями рассматриваемых символов в $s$ и $t$ , то есть состоянием $[i, j]$ .
Подзадача, соответствующая состоянию $[i, j]$ , такова: **минимальное число операций редактирования, необходимое для преобразования первых $i$ символов строки $s$ в первые $j$ символов строки $t$**.
@@ -47,7 +47,7 @@
![Переходы состояния в задаче о расстоянии редактирования](edit_distance_problem.assets/edit_distance_state_transfer.png)
Согласно этому анализу оптимальная подструктура такова: минимальное число шагов редактирования для $dp[i, j]$ равно минимуму из трех значений - $dp[i, j-1]$ , $dp[i-1, j]$ и $dp[i-1, j-1]$ - плюс цена текущей операции редактирования $1$ . Значит, уравнение перехода состояния имеет вид:
Согласно этому анализу оптимальная подструктура такова: минимальное число шагов редактирования для $dp[i, j]$ равно минимуму из трех значений - $dp[i, j-1]$ , $dp[i-1, j]$ и $dp[i-1, j-1]$ - плюс $1$ шаг за текущее редактирование. Значит, уравнение перехода состояния имеет вид:
$$
dp[i, j] = \min(dp[i, j-1], dp[i-1, j], dp[i-1, j-1]) + 1
@@ -71,7 +71,7 @@ $$
[file]{edit_distance}-[class]{}-[func]{edit_distance_dp}
```
Как показано на рисунке ниже, процесс переходов состояния в задаче о расстоянии редактирования очень похож на процесс в задачах о рюкзаке: в обоих случаях это заполнение двумерной сетки.
Как показано на рисунке ниже, процесс переходов состояния в задаче о расстоянии редактирования очень похож на задачи о рюкзаке: и там и здесь его можно рассматривать как заполнение двумерной сетки.
=== "<1>"
![Процесс динамического программирования для расстояния редактирования](edit_distance_problem.assets/edit_distance_dp_step1.png)
@@ -122,7 +122,7 @@ $$
Поскольку $dp[i,j]$ зависит от значения сверху $dp[i-1, j]$ , слева $dp[i, j-1]$ и слева сверху $dp[i-1, j-1]$ , прямой обход после оптимизации памяти теряет значение слева сверху, а обратный обход не позволяет заранее построить значение слева $dp[i, j-1]$ . Значит, оба наивных варианта обхода здесь непригодны.
Чтобы решить эту проблему, можно использовать переменную `leftup` для временного сохранения значения слева сверху $dp[i-1, j-1]$ ; после этого остается учитывать только верхнее и левое значения. Тогда ситуация становится эквивалентной задаче о полном рюкзаке, и можно выполнять прямой обход. Код приведен ниже:
Чтобы решить эту проблему, можно использовать переменную `leftup` для временного сохранения значения слева сверху $dp[i-1, j-1]$ ; после этого остается учитывать только верхнее и левое значения. Тогда ситуация становится аналогичной задаче о полном рюкзаке, и можно выполнять прямой обход. Код приведен ниже:
```src
[file]{edit_distance}-[class]{}-[func]{edit_distance_dp_comp}