Реализации алгоритмов/Расстояние Левенштейна: различия между версиями

Содержимое удалено Содержимое добавлено
→‎C++: Это логически неверно использовать typename T::value_type, т.к. для строки он равен char, из-за чего могут спокойно происходить переполнения. Тест: 1000 букв a, 1000 букв b.
→‎C++: Изменён код C++. Теперь он использует min(m, n) памяти вместо m * n памяти. Добавлено код на обобщённое расстояние Левенштейна
Строка 530:
 
== [[w:C++|C++]] ==
Имплементация использует <math>\sim~ min(m, n)</math> памяти:
<!--
Зависимости: Нет. Стандартный Си++.
Автор: ВладиславНиколай ЛазаренкоКоролев, vladislav.lazarenkokorolevns98@gmail.com, КиевМосква, УкраинаРоссия.
Дата: 1605 сентябряянваря 20072019 г.
Copyright: Если хотите, можете угостить соком, пиво не пью :-)
Дата: 16 сентября 2007 г.
-->
<source lang="CPP">
template<typename T>
#include <vector>
typename T::size_type levenshtein_distanceLevensteinDistance(const T & srcs, const T & dst) {
#include <algorithm>
const T &t) {
if (s.size() > t.size()) {
return LevensteinDistance(t, s);
}
 
template < using T_size_t = typename T>::size_type;
const T_size_t min_size = s.size(), max_size = t.size();
typename T::size_type levenshtein_distance(const T & src, const T & dst) {
std::vector<T_size_t> lev_dist(min_size + 1);
const typename T::size_type m = src.size();
const typename T::size_type n = dst.size();
if (m == 0) {
return n;
}
if (n == 0) {
return m;
}
 
for (typename T::size_typeT_size_t i = 0; i <= nmin_size; ++i) {
std::vector< std::vector<typename T::size_type> > matrix(m + 1);
matrix[0] lev_dist[i] = i;
}
 
for (typename T::size_typeT_size_t ij = 01; ij <= mmax_size; ++ij) {
T_size_t previous_diagonal = lev_dist[0], previous_diagonal_save;
matrix[i].resize(n + 1);
matrix[i] ++lev_dist[0] = i;
}
for (typename T::size_type i = 0; i <= n; ++i) {
matrix[0][i] = i;
}
 
for(typename T::size_type(T_size_t ji = 1; ji <= nmin_size; ++ji) {
typename T::size_type above_cell, left_cell, diagonal_cell, cost;
previous_diagonal_save = lev_dist[i];
 
for (typename T::size_type i = 1; if (s[i <- 1] == m;t[j ++i- 1]) {
lev_dist[i] = previous_diagonal;
for(typename T::size_type j = 1; j <= n; ++j) {
cost = src[i - 1] == dst[j} -else 1] ? 0 : 1;{
lev_dist[i] = std::min(std::min(lev_dist[i - 1], lev_dist[i]), previous_diagonal) + 1;
above_cell = matrix[i - 1][j];
left_cell = matrix[i][j - 1]; }
previous_diagonal = previous_diagonal_save;
diagonal_cell = matrix[i - 1][j - 1];
}
matrix[i][j] = std::min(std::min(above_cell + 1, left_cell + 1), diagonal_cell + cost);
}
}
 
return matrix[m]lev_dist[nmin_size];
}
</source>
Строка 584 ⟶ 578 :
const std::string src = "125";
const std::string dst = "521";
const std::string::size_type distance = levenshtein_distanceLevensteinDistance(src, dst);
...
</source>
 
Имплементация обобщённого расстояния Левенштейна с произвольными стоимостями вставки, удаления и замены символа:
 
<!--
Зависимости: Нет. Стандартный Си++.
Автор: Николай Королев, korolevns98@gmail.com, Москва, Россия.
Дата: 05 января 2019 г.
-->
<source lang="CPP">
#include <algorithm>
#include <vector>
 
template<typename T>
typename T::size_type GeneralizedLevensteinDistance(const T &s,
const T &t,
typename T::size_type insert_cost = 1,
typename T::size_type delete_cost = 1,
typename T::size_type replace_cost = 1) {
if (s.size() > t.size()) {
return GeneralizedLevensteinDistance(t, s, delete_cost, insert_cost, replace_cost);
}
 
const using T_size_t = typename T::size_type m = src.size();
const T_size_t min_size = s.size(), max_size = t.size();
std::vector<T_size_t> lev_dist(min_size + 1);
 
lev_dist[0] = 0;
for (T_size_t i = 1; i <= min_size; ++i) {
lev_dist[i] = lev_dist[i - 1] + delete_cost;
}
 
for (T_size_t j = 1; j <= max_size; ++j) {
T_size_t previous_diagonal = lev_dist[0], previous_diagonal_save;
lev_dist[0] += insert_cost;
 
for (T_size_t i = 1; i <= min_size; ++i) {
previous_diagonal_save = lev_dist[i];
diagonal_cell = matrix if (s[i - 1] == t[j - 1];) {
lev_dist[i] = previous_diagonal;
} else {
lev_dist[i] = std::min(std::min(lev_dist[i - 1] + delete_cost, lev_dist[i] + insert_cost), previous_diagonal + replace_cost);
}
previous_diagonal = previous_diagonal_save;
}
}
 
return lev_dist[min_size];
}
</source>