#include<bits/stdc++.h> using i64 = longlong; using u64 = unsignedlonglong; using i128 = __int128; #define int i64 #define pb push_back #define ep emplace #define eb emplace_back usingnamespace std; intread(int x = 0, int f = 0, char ch = getchar()){ while (ch < 48or57 < ch) f = ch == 45, ch = getchar(); while (48 <= ch and ch <= 57) x = x * 10 + ch - 48, ch = getchar(); return f ? -x : x; } #define debug(x) cout << #x << " = " << x << "\n"; #define vdebug(a) cout << #a << " = "; for (auto x : a) cout << x << " "; cout << "\n"; template <classT1, classT2> ostream &operator<<(ostream &os, const std::pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; }; template <classT> ostream &operator<<(ostream &os, const vector<T> &as) { constint sz = as.size(); os << "["; for (int i = 0; i < sz; i++) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; } template <classT> voidpv(T a, T b){ for (T i = a; i != b; i++) cerr << *i << " "; cerr << '\n'; } using pii = pair<int, int>; constint inf = 1e18;
structSAM { staticconstexprint ALPHABET_SIZE = 26; structNode { int len; int link; std::array<int, ALPHABET_SIZE> next; Node() : len{}, link{}, next{} {} }; std::vector<Node> t; SAM() { init(); } voidinit(){ t.assign(2, Node()); t[0].next.fill(1); t[0].len = -1; } intnewNode(){ t.emplace_back(); return t.size() - 1; } intextend(int p, int c){ if (t[p].next[c]) { int q = t[p].next[c]; if (t[q].len == t[p].len + 1) { return q; } int r = newNode(); t[r].len = t[p].len + 1; t[r].link = t[q].link; t[r].next = t[q].next; t[q].link = r; while (t[p].next[c] == q) { t[p].next[c] = r; p = t[p].link; } return r; } int cur = newNode(); t[cur].len = t[p].len + 1; while (!t[p].next[c]) { t[p].next[c] = cur; p = t[p].link; } t[cur].link = extend(p, c); return cur; } intnext(int p, int x){ return t[p].next[x]; } intlink(int p){ return t[p].link; } intlen(int p){ return t[p].len; } intsize(){ return t.size(); } };
voidsolve(){ string A, B; cin >> A >> B; SAM sam; for (int p = 1; auto ch : A) { if (ch < 'a'or ch > 'z') continue; p = sam.extend(p, ch - 'a'); }
int ans = 0; for (int v = 1, len = 0; auto ch : B) { int c = ch - 'a'; if (sam.next(v, c)) { v = sam.next(v, c); len++; } else { while (v and !sam.next(v, c)) { v = sam.link(v); } if (v == 0) { v = 1, len = 0; continue; }
len = sam.len(v) + 1; v = sam.next(v, c); } ans = max(ans, len); } cout << ans << '\n'; }
signedmain(){ // for (int T = read(); T--; solve()); solve(); return0; }
structSAM { // static constexpr int ALPHABET_SIZE = 26; structNode { int len; int link; // std::array<int, ALPHABET_SIZE> next; map<int, int> next; Node() : len{}, link{}, next{} {} }; std::vector<Node> t; SAM() { init(); } voidinit(){ t.assign(2, Node()); // t[0].next.fill(1); t[0].len = -1; } intnewNode(){ t.emplace_back(); return t.size() - 1; } intextend(int p, int c){ if (p == 0) return1; if (t[p].next.count(c)) { int q = t[p].next[c]; if (t[q].len == t[p].len + 1) { return q; } int r = newNode(); t[r].len = t[p].len + 1; t[r].link = t[q].link; t[r].next = t[q].next; t[q].link = r; while (t[p].next[c] == q) { t[p].next[c] = r; p = t[p].link; } return r; } int cur = newNode(); t[cur].len = t[p].len + 1; while (!t[p].next.count(c)) { t[p].next[c] = cur; p = t[p].link; } t[cur].link = extend(p, c); return cur; } intnext(int p, int x){ return t[p].next[x]; } intlink(int p){ return t[p].link; } intlen(int p){ return t[p].len; } intsize(){ return t.size(); } };
voidsolve(){ int n = read(); SAM sam;
int ans = 0; for (int i = 1, p = 1; i <= n; i++) { int x = read(); int ch = x; p = sam.extend(p, ch); ans += sam.len(p) - sam.len(sam.link(p)); cout << ans << '\n'; } }
P5341 [TJOI2019] 甲苯先生和大中锋的字符串
我们有一个字符串 S 和一个数 k,要找出出现恰好 k 次的所有子串,然后按照“子串长度”分组,数一数每个长度的子串数量,取数量最多的长度输出(多解选最长),如果没有恰好 k 次的子串就输出 -1。
voidsolve(){ string s; cin >> s; int k = read(); SAM sam;
vector<int> endpos; for (int p = 1; auto ch : s) { p = sam.extend(p, ch - 'a'); endpos.eb(p); }
vector<int> cnt(sam.size(), 0); for (int s : endpos) { cnt[s] += 1; }
vector<int> order(sam.size()); ranges::iota(order, 0); ranges::sort(order, [&](int a, int b) { return sam.len(a) > sam.len(b); });
for (int u : order) { if (u == 0) continue; cnt[sam.link(u)] += cnt[u]; }
int n = s.size(); vector<int> c(n + 5); for (int u = 1; u < sam.size(); u++) { if (cnt[u] != k) continue;
int p = sam.link(u); c[sam.len(p) + 1]++; c[sam.len(u) + 1]--; }
int ans = 0, res = -1; for (int i = 1; i <= n; i++) { c[i] += c[i - 1]; if (c[i] >= res or (c[i] == res and i > ans)) res = c[i], ans = i; } if (res == 0) ans = -1;