Submission #1017704

#TimeUsernameProblemLanguageResultExecution timeMemory
1017704caterpillowMatching (CEOI11_mat)C++17
100 / 100
127 ms49316 KiB
#include <bits/stdc++.h> using namespace std; #pragma GCC optimize("O3,unroll-loops") #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") using ll = long long; using pi = pair<int, int>; #define vt vector #define f first #define s second #define pb push_back #define all(x) x.begin(), x.end() #define size(x) ((int) (x).size()) #define FOR(i, a, b) for (int i = (a); i < (b); i++) #define ROF(i, a, b) for (int i = (b) - 1; i >= (a); i--) #define F0R(i, b) FOR (i, 0, b) #define endl '\n' const ll INF = 1e18; const int inf = 1e9; inline namespace FastIO { const int BSZ = 1 << 15; char ibuf[BSZ]; int ipos, ilen; char nc() { if (ipos == ilen) { ipos = 0; ilen = fread(ibuf,1,BSZ,stdin); if (!ilen) return EOF; } return ibuf[ipos++]; } void rs(string& x) { char ch; while (isspace(ch = nc())); do { x += ch; } while (!isspace(ch = nc()) && ch != EOF); } template<class T> void ri(T& x) { char ch; int sgn = 1; while (!isdigit(ch = nc())) if (ch == '-') sgn *= -1; x = ch - '0'; while (isdigit(ch = nc())) x = x * 10 + (ch - '0'); x *= sgn; } template<class T, class... Ts> void ri(T& t, Ts&... ts) { ri(t); ri(ts...); } char obuf[BSZ], numBuf[100]; int opos; void flushOut() { fwrite(obuf,1,opos,stdout); opos = 0; } void wc(char c) { if (opos == BSZ) flushOut(); obuf[opos++] = c; } void ws(string s) { for (char& c : s) wc(c); } template<class T> void wi(T x, char after = '\0') { if (x < 0) wc('-'), x *= -1; int len = 0; for (; x >= 10; x /= 10) numBuf[len++] = '0' + (x % 10); wc('0' + x); ROF (i, 0, len) wc(numBuf[i]); if (after) wc(after); } } /* let fb[i] be how much you should shift your pattern to the right if you mismatch at index i i cant be 0 let s be the prefix that we currently know matches if there does not exist a suffix of this prefix which matches the prefix of s, then we can slide our pattern to the end of s, since we know that it definitely wont match inside this prefix however, if there does exist a suffix that matches the prefix, we can slide our pattern such that our prefix is now aligned with this matching suffix and then start matching from there ------------------------------------------------------------------------------------------- let the pattern be p let s be the prefix of the pattern of length i fb[i] = the length of the longest suffix in s such that this suffix matches the prefix of s define fb[0] = -1 if we can compute this array, then if we know that we have a prefix of length i that matches the string (so char at index i is the first mismatch) we can delete the first i - fb[i] characters of the string, and we will know that characters up to fb[i] - 1 will match the pattern of this new string and index fb[i] may or may not be a mismatch for example, the string abcdabc would have fb = [-1, 0, 0, 0, 0, 1, 2, 3] ------------------------------------------------------------------------------------------- to compute this array, we would like to know many characters each suffix of the pattern p match with itself for example, abcdabc would be [7, 0, 0, 0, 3, 0, 0] let this array be called dp then, calculating fb[i] in increasing i, let j be the leftmost index among the indices strictly less than i such that j + dp[j] >= i fb[i] = i - j we need to exclude dp[0], since we only care about proper suffixes ------------------------------------------------------------------------------------------- to calculate dp, idk */ // automatically pad on either side struct DSU { vt<int> e, rep; void init(int n) { e.resize(n + 2, -1); rep.resize(n + 2); iota(all(rep), 0); } int _find(int x) { // just remember to add 1 before calling return e[x] < 0 ? x : e[x] = _find(e[x]); } void _unite(int x, int y) { x = _find(x), y = _find(y); if (e[x] < e[y]) swap(x, y), swap(rep[x], rep[y]); e[y] += e[x]; e[x] = y; } inline void unite(int x, int y) { _unite(x + 1, y + 1); } inline int find(int x) { return rep[_find(x + 1)] - 1; } }; int m, n; vt<int> pat; vt<pi> comp; vt<int> h; // check match at index j of the pattern starting at index i in str bool match(int i, int j, vt<int>& str) { pi prv = comp[j - i]; bool good = true; if (prv.f != -1) good &= str[prv.f + i] < str[j]; if (prv.s != -1) good &= str[j] < str[prv.s + i]; return good; } vt<int> dp; void compute_dp() { dp.resize(m, inf); dp[0] = 0; int j = 1; // the first mismatched character starting from index i FOR (i, 1, m) { while (j < m && match(i, j, pat)) j++; dp[i] = j - i; int k = 1; while (i + k < m && i + k + dp[k] < j) { // case 1: we know the mismatch happens in our good prefix dp[i + k] = dp[k]; k++; } i += k - 1; } } vt<int> fb; void compute_fallback() { fb.resize(m + 1, -1); vt<int> q; int f = 0; FOR (i, 1, m + 1) { q.pb(i - 1); while (f < size(q) && q[f] + dp[q[f]] < i) f++; if (f == size(q)) fb[i] = 0; else fb[i] = i - q[f]; } } using namespace FastIO; main() { ri(m, n); pat.resize(m); vt<int> rpat(m); F0R (i, m) ri(rpat[i]), pat[--rpat[i]] = i; comp.resize(m, {-1, -1}); DSU next_lower, next_higher; next_lower.init(m); next_higher.init(m); ROF (i, 0, m) { int lo = next_lower.find(pat[i] - 1); int hi = next_higher.find(pat[i] + 1); if (lo != -1) comp[i].f = rpat[lo]; if (hi != m) comp[i].s = rpat[hi]; next_lower.unite(pat[i], pat[i] - 1); next_higher.unite(pat[i], pat[i] + 1); } h.resize(n); F0R (i, n) ri(h[i]); compute_dp(); compute_fallback(); vt<int> out; int i = 0; int off = 0; while (i + off < n) { while (i + off < n && i < m && match(off, off + i, h)) i++; if (i == m) out.pb(off); off += i - fb[i]; i = fb[i]; } wi(size(out), '\n'); for (int e : out) wi(e + 1, ' '); wc('\n'); flushOut(); }

Compilation message (stderr)

mat.cpp:180:1: warning: ISO C++ forbids declaration of 'main' with no type [-Wreturn-type]
  180 | main() {
      | ^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...