USACO Platinum 2023 March - Pareidolia
Author: Aakash Gokhale
Explanation
Let's first try to solve the problem without updates on a single string. Notice that it is always optimal to take the earliest and then the earliest and then the earliest after that and so on because it maximizes the number of places you can search to find the next letter of "bessie".
Now let's try to solve the problem without updates for all substrings. Let be the number of positions of the string we have processed so far such that if we apply the greedy strategy described above, the next character we need to add is the th character ( indexed) of the string "bessie". We also need to add the substring starting from the current index. If the current letter of the string is , then the next letter we need to add is so in this case we add to . In every other case, we need to add to because the next character we add to fill "bessie" is .
C++
#include <bits/stdc++.h>using namespace std;int main() {string s;cin >> s;int n = s.size();s = '$' + s;long long ans = 0;vector<long long> dp(6);
Notice that we can represent the transition from to as a system of linear reccurences which depend on the letter.
B:
E:
S:
I:
Identity (Any letter other than , , , or ):
We can represent these linear recurrences with matrices where each letter of the string has its respective matrix. Now, multiplying all these matrices together will allow us to compute our answer. Note that since matrix multiplication is non commutative, we need to pay attention to the order of the two matrices that we are multiplying. In this case, we multiply matrices representing earlier indexes by matrices represting later indexes (rather than matrices representing later indexes by matrices represting later indexes).
We can optimize updates by building a segment tree on the matrices and updating each node with the respective matrix based on the given letter.
Note that if the letter is , we need to set as .
The -th column of each matrix represents , the th column of each matrix represents the answer, and the th column of each matrix is a constant so we can add to or at every index.
To extract the answer from the matrices, we can multiply the matrix representing our initial state by the product of all the matrices and look at the value in the nd to last column, which we defined to be the answer.
This ends up being equivalent to the value located at of the product of all the matrices.
Implementation
The constant factor for this solution is high, so you may need to do some of the following optimizations to pass the test cases:
- Use C++.
- We can skip all s while multiplying the matrices to speed up the multiplication.
- Use fastio and '\n' instead of endl.
- Build the segtree in rather than updating each index individually in .
- Use pragmas (Ofast, O3, unroll-loops, etc ...).
Time Complexity:
C++
#include <bits/stdc++.h>using namespace std;const int sz = 8, N = 2e5 + 5;using mat = array<array<long long, 8>, 8>;mat operator*(mat const &a, mat const &b) {mat r;for (int i = 0; i < sz; i++) {
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!