#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "fuzzy/common.h"
unsigned damerau_levenshtein(const char* str1, const char* str2) {
assert(str1 != NULL);
assert(str2 != NULL);
const unsigned alpha_size = 255;
size_t str1_len = strlen(str1);
size_t str2_len = strlen(str2);
if (str1_len == 0) {
return str2_len;
}
if (str2_len == 0) {
return str1_len;
}
while (str1_len > 0 && str2_len > 0 && EQ(str1[0], str2[0])) {
str1++, str2++;
str1_len--, str2_len--;
}
const unsigned INFINITY = str1_len + str2_len;
unsigned row, col;
unsigned* dict = calloc(alpha_size, sizeof(unsigned));
size_t m_rows = str1_len + 2; size_t m_cols = str2_len + 2;
unsigned** matrix = malloc(m_rows * sizeof(unsigned*));
for (unsigned i = 0; i < m_rows; i++) {
matrix[i] = calloc(m_cols, sizeof(unsigned));
}
matrix[0][0] = INFINITY;
for (row = 1; row < m_rows; row++) {
matrix[row][0] = INFINITY;
matrix[row][1] = row - 1;
}
for (col = 1; col < m_cols; col++) {
matrix[0][col] = INFINITY;
matrix[1][col] = col - 1;
}
unsigned db;
unsigned i, k;
unsigned cost;
for (row = 1; row <= str1_len; row++) {
db = 0;
for (col = 1; col <= str2_len; col++) {
i = dict[(unsigned)str2[col - 1]];
k = db;
cost = EQ(str1[row - 1], str2[col - 1]) ? 0 : 1;
if (cost == 0) {
db = col;
}
matrix[row + 1][col + 1] =
MIN4(matrix[row][col] + cost, matrix[row + 1][col] + 1, matrix[row][col + 1] + 1,
matrix[i][k] + (row - i - 1) + (col - k - 1) + 1);
}
dict[(unsigned)str1[row - 1]] = row;
}
unsigned result = matrix[m_rows - 1][m_cols - 1];
free(dict);
for (unsigned i = 0; i < m_rows; i++) {
free(matrix[i]);
}
free(matrix);
return result;
}