|
|
auto subsequence_boundary(auto start, auto end,auto pred) {
|
|
using live_iterator = decltype(start);
|
|
using distance_t = std::invoke_result_t<decltype(std::distance<live_iterator>), live_iterator, decltype(end)>;
|
|
distance_t distance = std::distance(start, end);
|
|
|
|
if(distance < 1) {
|
|
return start;
|
|
}
|
|
|
|
if(distance == 1) {
|
|
return ++start;
|
|
}
|
|
|
|
live_iterator next = start;
|
|
++next;
|
|
|
|
while(not pred(*start, *next)) {
|
|
++start;
|
|
++next;
|
|
if(next == end) return next;
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
auto longest_matching_subsequence(auto start, auto end, auto pred) {
|
|
using live_iterator = decltype(start);
|
|
using distance_t = std::invoke_result_t<decltype(std::distance<live_iterator>), live_iterator, decltype(end)>;
|
|
live_iterator current = start;
|
|
struct {
|
|
live_iterator best_s;
|
|
live_iterator best_e;
|
|
} results;
|
|
results.best_s = start;
|
|
results.best_e = start;
|
|
distance_t best_length = 0;
|
|
while(current != end) {
|
|
live_iterator next = subsequence_boundary(current, end, pred);
|
|
distance_t subsequence_length = std::distance(current, next);
|
|
if(subsequence_length > best_length) {
|
|
results.best_s = current;
|
|
results.best_e = next;
|
|
best_length = subsequence_length;
|
|
}
|
|
current = next;
|
|
}
|
|
return results;
|
|
}
|
|
|
|
TEST_CASE("Subsequence") {
|
|
std::vector<int> list = {0,1,2,3,4,5,0,1,0,2,5,8,7};
|
|
auto [s,e] = longest_matching_subsequence(list.begin(), list.end(), std::greater<int>{});
|
|
REQUIRE(std::distance(s,e) == 6);
|
|
}
|