P5115 Check, Check, Check one two!
P5115 Check, Check, Check one two!
看到题目,我首先想到建出正反串 SA 及其
稍微观察一下
对于
理论可以做到关于长度加字符集线性(线性 SA,线性区间 RMQ),但不实用。
听说官方题解是
#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;
constexpr int N = 1e5 + 5;
ull f[N], ans;
int n, k1, k2;
char s[N];
ull S1(ull x) {return x * (x + 1) / 2;}
ull S2(ull x) {return x * (x + 1) * (x + x + 1) / 6;}
int sa[N], rk[N], ork[N], buc[N], id[N], ht[N];
bool cmp(int a, int b, int w) {return ork[a] == ork[b] && ork[a + w] == ork[b + w];}
void build() {
int m = 1 << 7, p = 0;
for(int i = 1; i <= n; i++) buc[rk[i] = s[i]]++;
for(int i = 1; i <= m; i++) buc[i] += buc[i - 1];
for(int i = n; i; i--) sa[buc[rk[i]]--] = i;
for(int w = 1; ; w <<= 1, m = p, p = 0) {
for(int i = n - w + 1; i <= n; i++) id[++p] = i;
for(int i = 1; i <= n; i++) if(sa[i] > w) id[++p] = sa[i] - w;
memset(buc, 0, sizeof(buc));
memcpy(ork, rk, sizeof(rk)), p = 0;
for(int i = 1; i <= n; i++) buc[rk[i]]++;
for(int i = 1; i <= m; i++) buc[i] += buc[i - 1];
for(int i = n; i; i--) sa[buc[rk[id[i]]]--] = id[i];
for(int i = 1; i <= n; i++) rk[sa[i]] = cmp(sa[i - 1], sa[i], w) ? p : ++p;
if(p == n) break;
}
for(int i = 1, k = 0; i <= n; i++) {
if(k) k--;
while(s[i + k] == s[sa[rk[i] - 1] + k]) k++;
ht[rk[i]] = k;
}
}
ull calc(char lim) {
static int stc[N], w[N], top;
ull cur = 0, ans = top = 0;
for(int i = 2; i <= n; i++) {
int wid = lim ? s[sa[i - 1] - 1] == lim : 1;
while(top && stc[top] >= ht[i]) cur -= w[top] * f[stc[top]], wid += w[top--];
stc[++top] = ht[i], w[top] = wid, cur += wid * f[ht[i]];
if(lim ? s[sa[i] - 1] == lim : 1) ans += cur;
}
return ans;
}
int main() {
#ifdef ALEX_WEI
FILE* IN = freopen("1.in", "r", stdin);
FILE* OUT = freopen("1.out", "w", stdout);
#endif
cin >> s + 1 >> k1 >> k2, n = strlen(s + 1);
for(int L = 1; L <= n; L++) {
int l = max(1, L - k2 + 1), r = min(L, k1);
if(l > r) break;
f[L] = (S1(r) - S1(l - 1)) * (L + 1) - (S2(r) - S2(l - 1));
}
build(), ans += calc(0);
for(int i = 0; i < 26; i++) ans -= calc('a' + i);
cout << ans << "\n";
return 0;
}