step20
All Classes Namespaces Files Functions Variables Typedefs Pages
edit_distance.hpp
Go to the documentation of this file.
1// Andrew Naplavkov
2
3#ifndef STEP20_EDIT_DISTANCE_HPP
4#define STEP20_EDIT_DISTANCE_HPP
5
6#include "detail/hirschberg.hpp"
7#include "detail/utility.hpp"
8#include <cstdint>
9#include <optional>
10
12namespace detail {
13
14template <class Equal>
15struct table {
16 const Equal& eq;
17
18 template <std::random_access_iterator I1, std::random_access_iterator I2>
19 auto last_row(I1 first1, I1 last1, I2 first2, I2 last2) const
20 {
21 auto size1 = last1 - first1;
22 auto size2 = last2 - first2;
23 auto tbl = ring_table<intmax_t, 2>(size2 + 1);
24 for (decltype(size1) l = 0; l <= size1; ++l)
25 for (decltype(size2) r = 0; r <= size2; ++r) {
26 if (l == 0)
27 tbl[l][r] = -r;
28 else if (r == 0)
29 tbl[l][r] = -l;
30 else if (eq(first1[l - 1], first2[r - 1]))
31 tbl[l][r] = 1 + tbl[l - 1][r - 1];
32 else
33 tbl[l][r] = -1 + std::max({tbl[l - 1][r - 1],
34 tbl[l - 1][r],
35 tbl[l][r - 1]});
36 }
37 return std::move(tbl[size1]);
38 }
39
40 template <bool transposed,
41 std::random_access_iterator I1,
42 std::random_access_iterator I2,
43 std::weakly_incrementable O>
44 O trace_col(I1 first1, I1 last1, I2 first2, I2 last2, O result) const
45 {
46 static auto make_pair = [](auto&& lhs, auto&& rhs) {
47 if constexpr (transposed)
48 return std::pair{rhs, lhs};
49 else
50 return std::pair{lhs, rhs};
51 };
52 while (first1 != last1) {
53 if (first2 == last2 ||
54 (first1 + 1 != last1 && !eq(*first1, *first2)))
55 *result++ = make_pair(*first1++, std::nullopt);
56 else
57 *result++ = make_pair(*first1++, *first2++);
58 }
59 return result;
60 }
61};
62
63} // namespace detail
64
66
73template <std::ranges::random_access_range R1,
74 std::ranges::random_access_range R2,
75 std::weakly_incrementable O,
76 class Equal = std::equal_to<>>
77O zip(const R1& r1, const R2& r2, O result, const Equal& eq = {})
78{
79 return hirschberg::trace(detail::table<Equal>{eq},
80 std::ranges::begin(r1),
81 std::ranges::end(r1),
82 std::ranges::begin(r2),
83 std::ranges::end(r2),
84 result);
85}
86
87} // namespace step20::edit_distance
88
89#endif // STEP20_EDIT_DISTANCE_HPP
Definition edit_distance.hpp:11
O zip(const R1 &r1, const R2 &r2, O result, const Equal &eq={})
Find the optimal sequence alignment between two strings.
Definition edit_distance.hpp:77