2024CSP前集训10.9
不想学东西了,,,
T4 25分,卡点没交上。
T1
普及题,之前还做过,没啥好说的。
T2
95
kmp 不对,挂了 5 分。
莫队奇偶性优化还是要加的。
对 \(s_{i,\dots,n}\) 跑 kmp,也就是跑了 \(n\) 遍,答案是:
while (m--) {
int l = read(), r = read();
int res = 0;
for (int i = l; i <= r; i++)
for (int j = i; j <= r; j++)
if (p[i][j])
if (vs[j][p[i][j]] == 0)
res++, vs[j][p[i][j]] = 1;
cout << (r - l + 1) * (r - l + 2) / 2 - res << '\n';
memset(vs, 0, sizeof(vs));
}
// 这是暴力
统计有多少个重复的串,再用总共的减去。
如果某个位置的 \(border\) 不为 \(0\),就说明前面出现了这个串,但是要注意每个位置同样长度的串只减一次。
改成莫队加减都很方便。
复杂度 \(O(n^2\sqrt q)\),但跑的挺快。
不会正解。
#include <bits/stdc++.h>
using namespace std;
int read() {
int x;
cin >> x;
return x;
}
const int maxN = 3e3 + 7, maxM = 2e4 + 7;
int n, m;
string s;
int p[maxN][maxN];
int vs[maxN][maxN];
int pos[maxN], len;
struct ques {
int l, r, id;
} q[maxM];
int ans[maxM];
int l = 1, r;
int res;
void addr() {
for (int i = l; i <= r; i++)
if (p[i][r]) {
if (!vs[r][p[i][r]])
res++;
vs[r][p[i][r]]++;
}
}
void addl() {
for (int i = l; i <= r; i++)
if (p[l][i]) {
if (!vs[i][p[l][i]])
res++;
vs[i][p[l][i]]++;
}
}
void dell() {
for (int i = l; i <= r; i++)
if (p[l][i]) {
vs[i][p[l][i]]--;
if (!vs[i][p[l][i]])
res--;
}
}
void delr() {
for (int i = l; i <= r; i++)
if (p[i][r]) {
vs[r][p[i][r]]--;
if (!vs[r][p[i][r]])
res--;
}
}
int main() {
freopen("substring.in", "r", stdin);
freopen("substring.out", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(nullptr);
n = read(), m = read();
cin >> s;
s = '@' + s;
for (int st = 1; st <= n; st++) {
string tmp;
for (int i = st; i <= n; i++)
tmp += s[i];
int *br = p[st];
br[0] = 0;
for (int i = 1; i < n - st + 1; i++) {
int j = br[i - 1];
while (j > 0 && tmp[i] != tmp[j])
j = br[j - 1];
if (tmp[i] == tmp[j])
br[i] = j + 1;
else
br[i] = 0;
}
for (int i = n - st, j = n; i >= 0; i--, j--)
br[j] = br[i], br[i] = 0;
}
len = max(n / sqrt(m), 1.0);
for (int i = 1; i <= n; i++)
pos[i] = (i - 1) / len + 1;
for (int i = 1; i <= m; i++)
q[i].l = read(), q[i].r = read(), q[i].id = i;
sort(q + 1, q + m + 1, [](ques A, ques B) {
if (pos[A.l] == pos[B.l])
return (pos[A.l] & 1) ? A.r < B.r : A.r > B.r;
return A.l < B.l;
});
for (int i = 1; i <= m; i++) {
while (r < q[i].r)
r++, addr();
while (q[i].l < l)
l--, addl();
while (l < q[i].l)
dell(), l++;
while (q[i].r < r)
delr(), r--;
int len = q[i].r - q[i].l + 1;
ans[q[i].id] = len * (len + 1) / 2 - res;
}
for (int i = 1; i <= m; i++)
cout << ans[i] << '\n';
}
T3
#include <bits/stdc++.h>
using namespace std;
using ubt = long long;
int read() {
int s = 0, w = 1;
char c = getchar();
while (!isdigit(c)) {
if (c == '-')
w = -w;
c = getchar();
}
while (isdigit(c)) {
s = s * 10 + c - 48;
c = getchar();
}
return w * s;
}
void pr(ubt x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
pr(x / 10);
putchar(x % 10 + 48);
}
#define end_ putchar('\n')
#define spc_ putchar(' ')
const int maxN = 4e5 + 7;
struct trie {
int n;
int ch[maxN][26];
ubt cnt[26];
void insert(string s, bool ty) {
int u = 0, len = s.length();
if (!ty) {
for (int i = 0; i < len; i++) {
int o = s[i] - 'a';
if (!ch[u][o])
ch[u][o] = ++n;
u = ch[u][o];
}
}
else {
for (int i = len - 1; ~i; i--) {
int o = s[i] - 'a';
if (!ch[u][o])
ch[u][o] = ++n, cnt[o]++;
u = ch[u][o];
}
}
}
} t1, t2;
int n;
ubt ans;
bool ok[26], flag[26];
int main() {
freopen("magic.in", "r", stdin);
freopen("magic.out", "w", stdout);
n = read();
for (int i = 1; i <= n; i++) {
string s;
cin >> s;
t1.insert(s, false), t2.insert(s, true);
int len = s.length();
ok[s[len - 1] - 'a'] = true;
if (len == 1 && !flag[s[0] - 'a'])
ans++, flag[s[0] - 'a'] = true;
}
for (int u = 1; u <= t1.n; u++)
for (int o = 0; o < 26; o++)
if (!t1.ch[u][o])
ans += t2.cnt[o];
else
ans += ok[o];
pr(ans), end_;
}