Skip to content

USACO 2024 December Contest Bronze Division - It's Mooin' Time#

Problem link: here

Video link: here

Solution Author: Stefan Dascalescu

Problem Solution#

This problem can be brute forced by counting the number of substrings of length 3 which respect the pattern and then add them in a set

For each modification, all we have to do is to check the new frequencies and see if they could be added instead

Keeping strings is doable using maps and sets or your preferred programming language's option.

Source codes#

The source codes in C++ and Python can be seen below.

#include <iostream>
#include <map>
#include <set>

using namespace std;

int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n, f;
    cin >> n >> f;

    string s;
    cin >> s;

    map<string, int> frequencies;
    set<string> valid;

    // find the initial strings
    for (int i = 0; i + 2 < n; i++) {
        if (s[i] != s[i+1] && s[i+1] == s[i+2]) {
            string moo; moo += s[i]; moo += s[i+1]; moo += s[i+2];
            frequencies[moo]++;
            if (frequencies[moo] >= f) {
                valid.insert(moo);
            }
        }
    }

    for (int i = 0; i < n; i++) {
        // undo updates
        for (int start = i-2; start <= i; start++) {
            if (start < 0 || start + 2 >= n) {
                continue;
            }
            if (s[start] != s[start+1] && s[start+1] == s[start+2]) {
                string moo; moo += s[start]; moo += s[start+1]; moo += s[start+2];
                frequencies[moo]--;
            }
        }
        char orig = s[i];
        // try each new letter
        for (char letter = 'a'; letter <= 'z'; letter++) {
            s[i] = letter;
            for (int start = i-2; start <= i; start++) {
                if (start < 0 || start + 2 >= n) {
                    continue;
                }
                if (s[start] != s[start+1] && s[start+1] == s[start+2]) {
                    string moo; moo += s[start]; moo += s[start+1]; moo += s[start+2];
                    frequencies[moo]++;
                    if (frequencies[moo] >= f) {
                        valid.insert(moo);
                    }
                }
            }
            for (int start = i-2; start <= i; start++) {
                if (start < 0 || start + 2 >= n) {
                    continue;
                }
                if (s[start] != s[start+1] && s[start+1] == s[start+2]) {
                    string moo; moo += s[start]; moo += s[start+1]; moo += s[start+2];
                    frequencies[moo]--;
                }
            }
        }

        s[i] = orig;
        // redo updates
        for (int start = i-2; start <= i; start++) {
            if (start < 0 || start + 2 >= n) {
                continue;
            }
            if (s[start] != s[start+1] && s[start+1] == s[start+2]) {
                string moo; moo += s[start]; moo += s[start+1]; moo += s[start+2];
                frequencies[moo]++;
            }
        }
    }

    cout << (int) valid.size() << '\n';
    for (auto s : valid) {
        cout << s << '\n';
    }
    return 0;
}
n, f = map(int, input().split())
s = list(input().strip())

frequencies = {}
valid = set()

# find the initial strings
for i in range(n - 2):
    if s[i] != s[i+1] and s[i+1] == s[i+2]:
        moo = s[i] + s[i+1] + s[i+2]
        frequencies[moo] = frequencies.get(moo, 0) + 1
        if frequencies[moo] >= f:
            valid.add(moo)

for i in range(n):
    # undo updates
    for start in range(i - 2, i + 1):
        if start < 0 or start + 2 >= n:
            continue
        if s[start] != s[start+1] and s[start+1] == s[start+2]:
            moo = s[start] + s[start+1] + s[start+2]
            frequencies[moo] -= 1

    orig = s[i]
    # try each new letter
    for letter in map(chr, range(97, 123)):
        s[i] = letter
        for start in range(i - 2, i + 1):
            if start < 0 or start + 2 >= n:
                continue
            if s[start] != s[start+1] and s[start+1] == s[start+2]:
                moo = s[start] + s[start+1] + s[start+2]
                frequencies[moo] = frequencies.get(moo, 0) + 1
                if frequencies[moo] >= f:
                    valid.add(moo)

        for start in range(i - 2, i + 1):
            if start < 0 or start + 2 >= n:
                continue
            if s[start] != s[start+1] and s[start+1] == s[start+2]:
                moo = s[start] + s[start+1] + s[start+2]
                frequencies[moo] -= 1

    s[i] = orig
    # redo updates
    for start in range(i - 2, i + 1):
        if start < 0 or start + 2 >= n:
            continue
        if s[start] != s[start+1] and s[start+1] == s[start+2]:
            moo = s[start] + s[start+1] + s[start+2]
            frequencies[moo] = frequencies.get(moo, 0) + 1

print(len(valid))
for moo in sorted(valid):
    print(moo)