QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#612235#7780. Dark LaTeX vs. Light LaTeXTJUHuangTaoWA 19ms324704kbC++204.1kb2024-10-05 09:39:352024-10-05 09:39:36

Judging History

你现在查看的是最新测评结果

  • [2024-11-25 20:53:52]
  • hack成功,自动添加数据
  • (/hack/1258)
  • [2024-10-05 09:39:36]
  • 评测
  • 测评结果:WA
  • 用时:19ms
  • 内存:324704kb
  • [2024-10-05 09:39:35]
  • 提交

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();
    int p = 1, len = 0;
    for (int i = 1; i <= n; i++) {
        while (p > 1 && !sam.c[p][s[i - 1] - 'a']) p = sam.fa[p], len = sam.len[p];
        if (sam.c[p][s[i - 1] - 'a']) p = sam.c[p][s[i - 1] - 'a'], len++;
        for (int j = 1; j <= len; j++)
            cnt[i - j + 1][i] = 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;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 7ms
memory: 324628kb

input:

abab
ab

output:

8

result:

ok 1 number(s): "8"

Test #2:

score: -100
Wrong Answer
time: 19ms
memory: 324704kb

input:

abab
abaaab

output:

23

result:

wrong answer 1st numbers differ - expected: '29', found: '23'