题解 CF1313E 【Concatenation with intersection】

xht

2020-02-26 13:42:52

Solution

exkmp 求出 $a$ 的每个后缀和 $s$ 的 LCP,以及 $b$ 的每个后缀和 $s^r$ 的 LCP。 统计每个 $a_i$ 开头的方案数,two pointers 在 $b$ 上扫到对应的区间,树状数组维护即可。 设 $n,m$ 同阶,总时间复杂度 $\mathcal O(n \log n)$,$\log$ 在树状数组上而不在求 LCP 上,常数较小。 ```cpp const int N = 1e6 + 7; int n, m, p[N], q[N], d[N], z[N]; ll c[N], ans; char a[N], b[N], s[N]; inline void Z(char *s, int n) { for (int i = 1; i <= n; i++) z[i] = 0; z[1] = n; for (int i = 2, l = 0, r = 0; i <= n; i++) { if (i <= r) z[i] = min(z[i-l+1], r - i + 1); while (i + z[i] <= n && s[i+z[i]] == s[z[i]+1]) ++z[i]; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } } inline void exkmp(char *s, int n, char *t, int m, int *p) { Z(t, m); for (int i = 1; i <= n; i++) p[i] = 0; for (int i = 1, l = 0, r = 0; i <= n; i++) { if (i <= r) p[i] = min(z[i-l+1], r - i + 1); while (i + p[i] <= n && s[i+p[i]] == t[p[i]+1]) ++p[i]; if (i + p[i] - 1 > r) l = i, r = i + p[i] - 1; } } inline void add(int x, int k) { if (!x) return; while (x <= m) c[x] += k, d[x] += k > 0 ? 1 : -1, x += x & -x; } inline pair<ll, int> ask(int x) { ll k = 0; int p = 0; while (x) k += c[x], p += d[x], x -= x & -x; return mp(k, p); } int main() { rd(n), rd(m); rds(a, n), rds(b, n), rds(s, m); exkmp(a, n, s, m, p); reverse(b + 1, b + n + 1); reverse(s + 1, s + m + 1); exkmp(b, n, s, m, q); reverse(q + 1, q + n + 1); for (int i = 1, j = 0; i <= n; i++) { while (j + 1 <= n && j + 1 < i + m - 1) { if (q[++j] == m) --q[j]; add(q[j], q[j]); } if (p[i] == m) --p[i]; pair<ll, int> x = ask(m), y = ask(m - p[i] - 1); ans += x.fi - y.fi - 1ll * (x.se - y.se) * (m - p[i] - 1); add(q[i], -q[i]); } print(ans); return 0; } ```