#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iostream>
#include <limits>
#include <map>
#include <set>
#include <string>

std::size_t longest_at_most_k_bytes(const std::string& text, std::size_t k) {
    if (k == 0) return 0;
    std::map<unsigned char, std::size_t> counts;
    std::size_t left = 0, best = 0;
    for (std::size_t right = 0; right < text.size(); ++right) {
        ++counts[static_cast<unsigned char>(text[right])];
        while (counts.size() > k) {
            const auto key = static_cast<unsigned char>(text[left]);
            auto it = counts.find(key);
            assert(it != counts.end() && it->second > 0);
            --it->second;
            if (it->second == 0) counts.erase(it);
            ++left;
        }
        best = std::max(best, (right + 1) - left);
    }
    return best;
}

std::size_t brute(const std::string& text, std::size_t k) {
    std::size_t best = 0;
    for (std::size_t left = 0; left < text.size(); ++left) {
        std::set<unsigned char> seen;
        for (std::size_t right = left; right < text.size(); ++right) {
            seen.insert(static_cast<unsigned char>(text[right]));
            if (seen.size() <= k)
                best = std::max(best, (right + 1) - left);
        }
    }
    return best;
}

void check(const std::string& text) {
    for (std::size_t k = 0; k <= 4; ++k)
        assert(longest_at_most_k_bytes(text, k) == brute(text, k));
}

void enumerate(std::string& text, std::size_t remaining) {
    check(text);
    if (remaining == 0) return;
    const char alphabet[] = {'a', 'b', '\0'};
    for (char ch : alphabet) {
        text.push_back(ch);
        enumerate(text, remaining - 1);
        text.pop_back();
    }
}

int main() {
    assert(longest_at_most_k_bytes("", 2) == 0);
    assert(longest_at_most_k_bytes("eceba", 2) == 3);
    assert(longest_at_most_k_bytes("aa", 1) == 2);
    assert(longest_at_most_k_bytes("abc", 0) == 0);
    const std::string with_zero = {'a', '\0', 'b', '\0', 'b'};
    assert(longest_at_most_k_bytes(with_zero, 2) == 4);
    const std::string char_limits = {
        std::numeric_limits<char>::min(),
        std::numeric_limits<char>::max(),
        std::numeric_limits<char>::min()
    };
    check(char_limits);
    std::string text;
    enumerate(text, 6);
    std::cout << "sliding window: all assertions passed\n";
}
