QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#612220 | #7780. Dark LaTeX vs. Light LaTeX | TJUHuangTao | WA | 12ms | 324852kb | C++20 | 4.2kb | 2024-10-05 09:26:48 | 2024-10-05 09:26:48 |
Judging History
answer
#include<bits/stdc++.h>
// #define int long long
#define ll long long
#define db double
#define i128 __int128_t
#define pii pair<int, int>
using namespace std;
const int maxn = 5e3 + 10;
const int maxm = 1e6 + 10;
struct exKMP {
int z[100010];
void get_z(string& c) {
int len = c.length();
int p = 0, k = 1, l;
z[0] = len;
while (p + 1 < len && c[p] == c[p + 1])
p++;
z[1] = p;
for (int i = 2; i < len; i++) {
p = k + z[k] - 1;
l = z[i - k];
if (i + l <= p)
z[i] = l;
else {
int j = max(0, p - i + 1);
while (i + j < len && c[i + j] == c[j])
j++;
z[i] = j;
k = i;
}
}
}
} Z;
struct SAM {
int tot, lst, len[maxm], fa[maxm], c[maxm][27];
int cnt[maxm];
SAM() { tot = lst = 1; }
int id[maxm], tong[maxm];
void clear() {
memset(len, 0, sizeof len);
memset(fa, 0, sizeof fa);
memset(c, 0, sizeof c);
memset(cnt, 0, sizeof cnt);
memset(id, 0, sizeof id);
memset(tong, 0, sizeof tong);
tot = lst = 1;
}
void topo() { //基数排序后, 逆序枚举为拓扑序
for (int i = 1; i <= tot; i++) tong[len[i]]++;
for (int i = 1; i <= tot; i++) tong[i] += tong[i - 1];
for (int i = tot; i; i--) id[tong[len[i]]--] = i;
}
void extend(char ch) {
int x = ch - 'a', cur = ++tot, u;
cnt[cur] = 1, len[cur] = len[lst] + 1;
for (u = lst; u && !c[u][x]; u = fa[u]) c[u][x] = cur;
if (!u) fa[cur] = 1;
else {
int v = c[u][x];
if (len[v] == len[u] + 1) fa[cur] = v;
else {
int clone = ++tot;
len[clone] = len[u] + 1, fa[clone] = fa[v];
memcpy(c[clone], c[v], sizeof c[v]); // 时间复杂度在这个地方
for (; u && c[u][x] == v; u = fa[u])
c[u][x] = clone;
fa[cur] = fa[v] = clone;
}
}
lst = cur;
}
} sam;
int sub[maxn][maxn];
int cnt[maxn][maxn];
void get_cnt(string s, string t) { // cnt[i][j] : S [i, j] 在 T 的出现次数
for (auto ch : t) sam.extend(ch);
sam.topo();
for (int i = sam.tot; i > 1; i--) {
int u = sam.id[i], v = sam.fa[u];
sam.cnt[v] += sam.cnt[u];
}
int n = s.length();
for (int i = 1; i <= n; i++) {
int p = 1;
for (int j = i; j <= n; j++) {
while (p > 1 && !sam.c[p][s[j - 1] - 'a']) p = sam.fa[p];
if (sam.c[p][s[j - 1] - 'a'])
p = sam.c[p][s[j - 1] - 'a'];
for (int k = sam.len[sam.fa[p]] + 1; k <= sam.len[p]; k++) {
// assert(j - k + 1 > 0);
cnt[max(0, j - k + 1)][j] = sam.cnt[p];
}
}
}
}
ll cal(string s, string t, int id) {
int n = s.length(), m = t.length();
ll ans = 0;
// cout << "same" << ans << endl;
get_cnt(s, t);
if (id == 0) {
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
ans += cnt[i][j];
}
for (int i = 1; i <= n; i++) {
string str2 = s.substr(i - 1);
Z.get_z(str2);
for (int j = 3; j <= str2.length(); j++) {
int mxlen = min(Z.z[j - 1], j - 1);
if (!mxlen) continue;
// 右端点在 j - 1, 左端点在 2 到 mxlen + 1
sub[i - 1 + j - 1][i - 1 + 2]++;
sub[i - 1 + j - 1][i - 1 + mxlen + 1 + 1]--;
}
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++) {
sub[i][j] += sub[i][j - 1];
if (sub[i][j] > 0) {
ans += sub[i][j] * cnt[j][i];
// cout << "l, r = " << j << " " << i << endl;
}
}
return ans;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
string s, t;
cin >> s >> t;
ll res = cal(s, t, 0);
memset(sub, 0, sizeof sub);
memset(cnt, 0, sizeof cnt);
sam.clear();
res += cal(t, s, 1);
cout << res << endl;
return 0;
}
詳細信息
Test #1:
score: 100
Accepted
time: 12ms
memory: 324812kb
input:
abab ab
output:
8
result:
ok 1 number(s): "8"
Test #2:
score: 0
Accepted
time: 11ms
memory: 324652kb
input:
abab abaaab
output:
29
result:
ok 1 number(s): "29"
Test #3:
score: 0
Accepted
time: 8ms
memory: 324712kb
input:
abcd abcde
output:
10
result:
ok 1 number(s): "10"
Test #4:
score: -100
Wrong Answer
time: 7ms
memory: 324852kb
input:
aaba ba
output:
7
result:
wrong answer 1st numbers differ - expected: '6', found: '7'