C++ Utilities 5.11.1
Useful C++ classes and routines such as argument parser, IO and conversion utilities
levenshtein.cpp
Go to the documentation of this file.
1#include "./levenshtein.h"
2
3#include "./math.h"
4#include "./multiarray.h"
5
6#include <iostream>
7#include <limits>
8#include <memory>
9
10using namespace std;
11
12namespace CppUtilities {
13
15
17using DistanceArray = MultiArray<size_t, NoneOwningMultiArray, size_t, size_t>;
18
31void initDistanceArray(DistanceArray &distanceArray, const size_t size1, const size_t size2)
32{
33 const auto maxDistance(size1 + size2);
34 distanceArray.at(0, 0) = maxDistance;
35 for (size_t i = 0; i <= size1; ++i) {
36 distanceArray.at(i + 1, 1) = i;
37 distanceArray.at(i + 1, 0) = maxDistance;
38 }
39 for (size_t i = 0; i <= size2; ++i) {
40 distanceArray.at(1, i + 1) = i;
41 distanceArray.at(0, i + 1) = maxDistance;
42 }
43}
44
47size_t performDamerauLevenshteinAlgorithm(
48 DistanceArray &distanceArray, const char *const str1, const size_t size1, const char *const str2, const size_t size2)
49{
50 size_t dist1[std::numeric_limits<unsigned char>::max() + 1] = { 0 };
51 for (size_t index1 = 1; index1 <= size1; ++index1) {
52 size_t dist2 = 0;
53 for (size_t index2 = 1; index2 <= size2; ++index2) {
54 const size_t substitution((str1[index1 - 1] == str2[index2 - 1]) ? 0 : 1);
55 const size_t transposition1(dist1[static_cast<unsigned char>(str2[index2 - 1])]);
56 const size_t transposition2(dist2);
57 if (!substitution) {
58 dist2 = index2;
59 }
60 // clang-format off
61 distanceArray.at(index1 + 1, index2 + 1) = CppUtilities::min(
62 distanceArray.at(index1, index2) + substitution, // substitution
63 distanceArray.at(index1 + 1, index2) + 1, // insertion
64 distanceArray.at(index1, index2 + 1) + 1, // deletion
65 distanceArray.at(transposition1, transposition2) + (index1 - transposition1 - 1) + 1 + (index2 - transposition2 - 1) // transposition
66 );
67 // clang-format on
68 }
69 dist1[static_cast<int>(str1[index1 - 1])] = index1;
70 }
71 return distanceArray.at(size1 + 1, size2 + 1);
72}
73
75template <typename DistanceArray>
76size_t performDamerauLevenshteinAlgorithmAllocatingOnHeap(
77 DistanceArray &distanceArray, const char *const str1, const size_t size1, const char *const str2, const size_t size2)
78{
79 std::vector<size_t> buffer(distanceArray.totalSize());
80 distanceArray.buffer() = buffer.data();
81 initDistanceArray(distanceArray, size1, size2);
82 return performDamerauLevenshteinAlgorithm(distanceArray, str1, size1, str2, size2);
83}
84
87template <typename DistanceArray>
88size_t performDamerauLevenshteinAlgorithmAllocatingOnStack(
89 DistanceArray &distanceArray, const char *const str1, const size_t size1, const char *const str2, const size_t size2)
90{
91 size_t buffer[128] = { 0 };
92 distanceArray.buffer() = buffer;
93 initDistanceArray(distanceArray, size1, size2);
94 return performDamerauLevenshteinAlgorithm(distanceArray, str1, size1, str2, size2);
95}
96
98
117std::size_t computeDamerauLevenshteinDistance(const char *const str1, const size_t size1, const char *const str2, const size_t size2)
118{
119 // allocate distance array
120 auto distanceArray(makeNoneOwningMultiArray<std::size_t>(size1 + 2, size2 + 2));
121 if (distanceArray.totalSize() <= 128) {
122 return performDamerauLevenshteinAlgorithmAllocatingOnStack(distanceArray, str1, size1, str2, size2);
123 } else {
124 return performDamerauLevenshteinAlgorithmAllocatingOnHeap(distanceArray, str1, size1, str2, size2);
125 }
126}
127
128} // namespace CppUtilities
Contains all utilities provides by the c++utilities library.
constexpr T max(T first, T second)
Returns the greatest of the given items.
Definition: math.h:100
constexpr T min(T first, T second)
Returns the smallest of the given items.
Definition: math.h:88
CPP_UTILITIES_EXPORT std::size_t computeDamerauLevenshteinDistance(const char *str1, std::size_t size1, const char *str2, std::size_t size2)
STL namespace.
constexpr int i