Skip to content

Commit

Permalink
Исправление метода расчёта Дамерау-Левенштейна
Browse files Browse the repository at this point in the history
  • Loading branch information
anyks committed Sep 14, 2020
1 parent 17e85f6 commit 825ea74
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 65 deletions.
2 changes: 2 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# [Change Log](https://github.com/anyks/alm/archive/release.tar.gz)

## [3.4.2](https://github.com/anyks/alm/archive/v3.4.2.tar.gz) Bug fixes

## [3.4.1](https://github.com/anyks/alm/archive/v3.4.1.tar.gz) Bug fixes

## [3.4.0](https://github.com/anyks/alm/archive/v3.4.0.tar.gz) Bug fixes
Expand Down
2 changes: 1 addition & 1 deletion app/alm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// Название языковой модели
#define ANYKS_LM_NAME "alm"
// Версия приложения
#define ANYKS_LM_VERSION "3.4.1"
#define ANYKS_LM_VERSION "3.4.2"
// Автор приложения
#define ANYKS_LM_AUTHOR "Yuriy Lobarev"
// Телефон автора
Expand Down
18 changes: 9 additions & 9 deletions include/levenshtein.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,52 +60,52 @@ namespace anyks {
* @param z третье число
* @return самое минимальное значение из 3-х чисел
*/
const u_short minimum(const u_short x, const u_short y, const u_short z) const noexcept;
const size_t minimum(const size_t x, const size_t y, const size_t z) const noexcept;
public:
/**
* mulct Определение количества штрафов на основе Дамерау-Левенштейна
* @param pattern шаблон с которым идет сравнение
* @param text исходный текст
* @return дистанция
*/
const u_short mulct(const string & pattern, const string & text) const noexcept;
const size_t mulct(const string & pattern, const string & text) const noexcept;
/**
* mulct Определение количества штрафов на основе Дамерау-Левенштейна
* @param pattern шаблон с которым идет сравнение
* @param text исходный текст
* @return дистанция
*/
const u_short mulct(const wstring & pattern, const wstring & text) const noexcept;
const size_t mulct(const wstring & pattern, const wstring & text) const noexcept;
public:
/**
* damerau Определение дистанции Дамерау-Левенштейна в фразах
* @param pattern шаблон с которым идет сравнение
* @param text исходный текст
* @return дистанция
*/
const u_short damerau(const string & pattern, const string & text) const noexcept;
const size_t damerau(const string & pattern, const string & text) const noexcept;
/**
* damerau Определение дистанции Дамерау-Левенштейна в фразах
* @param pattern шаблон с которым идет сравнение
* @param text исходный текст
* @return дистанция
*/
const u_short damerau(const wstring & pattern, const wstring & text) const noexcept;
const size_t damerau(const wstring & pattern, const wstring & text) const noexcept;
public:
/**
* distance Определение дистанции в фразах
* @param pattern шаблон с которым идет сравнение
* @param text исходный текст
* @return дистанция
*/
const u_short distance(const string & pattern, const string & text) const noexcept;
const size_t distance(const string & pattern, const string & text) const noexcept;
/**
* distance Определение дистанции в фразах
* @param pattern шаблон с которым идет сравнение
* @param text исходный текст
* @return дистанция
*/
const u_short distance(const wstring & pattern, const wstring & text) const noexcept;
const size_t distance(const wstring & pattern, const wstring & text) const noexcept;
public:
/**
* tanimoto Метод определения коэффициента Жаккара (частное — коэф. Танимото)
Expand All @@ -114,15 +114,15 @@ namespace anyks {
* @param stl размер подстроки при сравнении двух слов (от 1 до минимального размера слова)
* @return коэффициент Танимото
*/
const double tanimoto(const string & first, const string & second, const u_short stl = 2) const noexcept;
const double tanimoto(const string & first, const string & second, const size_t stl = 2) const noexcept;
/**
* tanimoto Метод определения коэффициента Жаккара (частное — коэф. Танимото)
* @param first первое слово
* @param second второе слово
* @param stl размер подстроки при сравнении двух слов (от 1 до минимального размера слова)
* @return коэффициент Танимото
*/
const double tanimoto(const wstring & first, const wstring & second, const u_short stl = 2) const noexcept;
const double tanimoto(const wstring & first, const wstring & second, const size_t stl = 2) const noexcept;
public:
/**
* weighted Метод определения веса сравниваемого слова
Expand Down
98 changes: 43 additions & 55 deletions src/levenshtein.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const double anyks::LEV::minimum(const double x, const double y, const double z)
* @param z третье число
* @return самое минимальное значение из 3-х чисел
*/
const u_short anyks::LEV::minimum(const u_short x, const u_short y, const u_short z) const noexcept {
const size_t anyks::LEV::minimum(const size_t x, const size_t y, const size_t z) const noexcept {
// Определяем минимальное значение
return lvmin(lvmin(x, y), z);
}
Expand All @@ -36,9 +36,9 @@ const u_short anyks::LEV::minimum(const u_short x, const u_short y, const u_shor
* @param text исходный текст
* @return дистанция
*/
const u_short anyks::LEV::mulct(const string & pattern, const string & text) const noexcept {
const size_t anyks::LEV::mulct(const string & pattern, const string & text) const noexcept {
// Результат работы функции
u_short result = 0;
size_t result = 0;
// Если шаблон для сравнения и исходный текст переданы
if(!pattern.empty() && !text.empty()){
// Объявляем конвертер
Expand All @@ -58,9 +58,9 @@ const u_short anyks::LEV::mulct(const string & pattern, const string & text) con
* @param text исходный текст
* @return дистанция
*/
const u_short anyks::LEV::mulct(const wstring & pattern, const wstring & text) const noexcept {
const size_t anyks::LEV::mulct(const wstring & pattern, const wstring & text) const noexcept {
// Результат работы функции
u_short result = 0;
size_t result = 0;
// Если шаблон для сравнения и исходный текст переданы
if(!pattern.empty() && !text.empty()){
// Дефолтный взвешиватель весов
Expand All @@ -87,7 +87,7 @@ const u_short anyks::LEV::mulct(const wstring & pattern, const wstring & text) c
return ((a == d) && (b == c) ? 0.0 : 1.0);
};
// Выполняем сравнение
result = u_short(this->weighted(pattern, text, &weighter));
result = size_t(this->weighted(pattern, text, &weighter));
}
// Выводим результат
return result;
Expand All @@ -98,9 +98,9 @@ const u_short anyks::LEV::mulct(const wstring & pattern, const wstring & text) c
* @param text исходный текст
* @return дистанция
*/
const u_short anyks::LEV::damerau(const string & pattern, const string & text) const noexcept {
const size_t anyks::LEV::damerau(const string & pattern, const string & text) const noexcept {
// Результат работы функции
u_short result = 0;
size_t result = 0;
// Если шаблон для сравнения и исходный текст переданы
if(!pattern.empty() && !text.empty()){
// Объявляем конвертер
Expand All @@ -120,9 +120,9 @@ const u_short anyks::LEV::damerau(const string & pattern, const string & text) c
* @param text исходный текст
* @return дистанция
*/
const u_short anyks::LEV::damerau(const wstring & pattern, const wstring & text) const noexcept {
const size_t anyks::LEV::damerau(const wstring & pattern, const wstring & text) const noexcept {
// Результат работы функции
u_short result = 0;
size_t result = 0;
// Если шаблон для сравнения и исходный текст переданы
if(!pattern.empty() && !text.empty()){
// Дефолтный взвешиватель весов
Expand All @@ -146,10 +146,10 @@ const u_short anyks::LEV::damerau(const wstring & pattern, const wstring & text)
* @return вес символа
*/
weighter.rep = [](const wchar_t a, const wchar_t b, const wchar_t c, const wchar_t d) noexcept {
return 1.0;
return ((a == d) && (b == c) ? 0.0 : 1.0);
};
// Выполняем сравнение
result = u_short(this->weighted(pattern, text, &weighter));
result = size_t(this->weighted(pattern, text, &weighter));
}
// Выводим результат
return result;
Expand All @@ -160,9 +160,9 @@ const u_short anyks::LEV::damerau(const wstring & pattern, const wstring & text)
* @param text исходный текст
* @return дистанция
*/
const u_short anyks::LEV::distance(const string & pattern, const string & text) const noexcept {
const size_t anyks::LEV::distance(const string & pattern, const string & text) const noexcept {
// Результат работы функции
u_short result = 0;
size_t result = 0;
// Если шаблон для сравнения и исходный текст переданы
if(!pattern.empty() && !text.empty()){
// Объявляем конвертер
Expand All @@ -182,48 +182,36 @@ const u_short anyks::LEV::distance(const string & pattern, const string & text)
* @param text исходный текст
* @return дистанция
*/
const u_short anyks::LEV::distance(const wstring & pattern, const wstring & text) const noexcept {
const size_t anyks::LEV::distance(const wstring & pattern, const wstring & text) const noexcept {
// Результат работы функции
u_short result = 0;
size_t result = 0;
// Если шаблон для сравнения и исходный текст переданы
if(!pattern.empty() && !text.empty()){
// Конвертируем строки
const wstring txt = text;
const wstring ptr = pattern;
// Определяем размер исходного текста
const u_short txtlen = txt.length();
// Определяем размер шаблона
const u_short ptrlen = ptr.length();
// Если исходный текст не передан, то разница в длину шаблона
if(txtlen == 0) return ptrlen;
// Если шаблон не передан, то разница в длину исходного текста
else if(ptrlen == 0) return txtlen;
// Выполняем создание матрицы
vector <vector <u_short>> table(ptrlen + 1, vector <u_short> (txtlen + 1));
// Заполняем столбцы в нулевой строке таблицы
for(u_short i = 0; i <= txtlen; ++i) table[0][i] = i;
// Заполняем строки в таблице
for(u_short i = 0; i <= ptrlen; ++i) table[i][0] = i;
// Переменные для измерения дистанции Левенштейна
u_short aboveCell, leftCell, diagonalCell, cost;
// Переходим по всем строкам начиная с 1-й строки
for(u_short i = 1; i <= ptrlen; ++i){
// Переходим по всем столбцам начиная с 1-го столбца
for(u_short j = 1; j <= txtlen; ++j){
// Если текущие два символа обеих строк одинаковы, то значение стоимости будет равна 0, иначе будет 1
cost = ((ptr[i - 1] == txt[j - 1]) ? 0 : 1);
// Находим указанную ячейку в текущей ячейке
aboveCell = table[i - 1][j];
// Находим левую ячейку в текущей ячейке
leftCell = table[i][j - 1];
// Находим диагональную ячейку в текущей ячейке
diagonalCell = table[i - 1][j - 1];
// Вычисляем текущее значение (редактируемое расстояние) и результат в текущей ячейки матрицы
table[i][j] = this->minimum(u_short(aboveCell + 1), u_short(leftCell + 1), u_short(diagonalCell + cost));
}
}
// Определяем результат (что и есть расстояние Левенштейна)
result = table[ptrlen][txtlen];
// Дефолтный взвешиватель весов
weighter_t weighter;
/**
* Функция для определения веса при вставке
* @param a символ вставки
* @return вес символа
*/
weighter.ins = [](const wchar_t a) noexcept {return 1.0;};
/**
* Функция для определения веса при удалении
* @param a символ удаления
* @return вес символа
*/
weighter.del = [](const wchar_t a) noexcept {return 1.0;};
/**
* Функция для определения веса при замене
* @param a заменяемый символ
* @param b символ замены
* @return вес символа
*/
weighter.rep = [](const wchar_t a, const wchar_t b, const wchar_t c, const wchar_t d) noexcept {
return 1.0;
};
// Выполняем сравнение
result = size_t(this->weighted(pattern, text, &weighter));
}
// Выводим результат
return result;
Expand All @@ -235,7 +223,7 @@ const u_short anyks::LEV::distance(const wstring & pattern, const wstring & text
* @param stl размер подстроки при сравнении двух слов (от 1 до минимального размера слова)
* @return коэффициент Танимото
*/
const double anyks::LEV::tanimoto(const string & first, const string & second, const u_short stl) const noexcept {
const double anyks::LEV::tanimoto(const string & first, const string & second, const size_t stl) const noexcept {
// Результат работы функции
double result = 0.0;
// Если первое и второе слово переданы
Expand All @@ -258,7 +246,7 @@ const double anyks::LEV::tanimoto(const string & first, const string & second, c
* @param stl размер подстроки при сравнении двух слов (от 1 до минимального размера слова)
* @return коэффициент Танимото
*/
const double anyks::LEV::tanimoto(const wstring & first, const wstring & second, const u_short stl) const noexcept {
const double anyks::LEV::tanimoto(const wstring & first, const wstring & second, const size_t stl) const noexcept {
// Результат работы функции
double result = 0.0;
// Если первое и второе слово переданы
Expand Down

0 comments on commit 825ea74

Please sign in to comment.