QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#606274#7876. Cyclic SubstringslonelywolfML 128ms417476kbC++203.8kb2024-10-03 00:10:472024-10-03 00:10:47

Judging History

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

  • [2024-10-03 00:10:47]
  • 评测
  • 测评结果:ML
  • 用时:128ms
  • 内存:417476kb
  • [2024-10-03 00:10:47]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;

#define int long long

struct PAM {
    static constexpr int ALPHABET_SIZE = 10;
    struct Node {
        int len;
        int fail;
        int dep;      // 以这个节点结尾的回文子串的数量(回文fail树的深度)
        int cnt = 0;  // 同样的回文结构出现次数
        array<int, ALPHABET_SIZE> next;
        // int mask = 0;用了多少种字母
        Node() : len{}, fail{}, dep{}, next{} {}
    };
    vector<Node> t;
    vector<int> idpos;  // idpos表示字符串字符位置到后缀自动机节点编号
    int last;
    string s;
    PAM() {
        init();
    }
    void init() {
        t.assign(2, Node());
        t[0].len = -1;  // 0:奇根
        last = 1;       // 1:偶根
        s.clear();
        idpos.assign(1, 0);
    }
    int newNode() {
        t.emplace_back();
        return t.size() - 1;
    }

    bool add(char c, char offset = '0') {
        int pos = s.size();
        s += c;
        int ch = c - offset;
        int cur = last, curlen = 0;

        while (true) {
            curlen = t[cur].len;
            if (pos - 1 - curlen >= 0 && s[pos - 1 - curlen] == s[pos]) {
            	break;
            }
            cur = t[cur].fail;
        }  // 找到在哪个节点后面建新点
        if (t[cur].next[ch]) {
            last = t[cur].next[ch];
            idpos.push_back(last);
            t[last].cnt += 1;
            return false;
        }

        int num = newNode();
        last = num;
        idpos.push_back(last);
        t[num].len = t[cur].len + 2;
        // 在这里加入题目需要维护的值
        // t[num].mask = t[cur].mask;
        // t[num].mask |= 1 << ch;
        t[cur].next[ch] = num;

        if (t[num].len == 1) {  // 如果为单字符,指向偶根
            t[num].fail = 1;
            t[num].dep = 1;
            t[num].cnt = 1;
            return true;
        }

        while (true) {  // 为新节点找fail,从父亲的fail开始找
            cur = t[cur].fail;
            curlen = t[cur].len;
            if (pos - 1 - curlen >= 0 && s[pos - 1 - curlen] == s[pos]) {
                t[num].fail = t[cur].next[ch];
                break;
            }
        }
        t[num].cnt = 1;
        t[num].dep = 1 + t[t[num].fail].dep;

        return true;
    }
    int tot = 0;
    void work(string tt) {
        for (auto x : tt) add(x);
        tot = t.size() - 1;
        for (int i = tot; i >= 0; i--) {
            int fa = t[i].fail;
            t[fa].cnt += t[i].cnt;
        }
    }
    int fail(int p) {
        return t[p].fail;
    }
    int len(int p) {
        return t[p].len;
    }
    int size() {
        return t.size();
    }
    int cnt(int p) {
        return t[p].cnt;
    }
};
void solve() {
    string s;
    cin >> s;
    PAM pam;
    pam.work(s);
    int ans = 0;
    int tot = pam.size() - 1;
    for (int i = 2; i <= tot; i++) {
        ans = max(ans, pam.cnt(i) * pam.len(i) * pam.len(i));
    }
    cout << ans << endl;
}

constexpr int mod = 998244353;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    string s;
    cin >> n >> s;

    string t = s + s;
    
    PAM ps, pt;
    ps.work(s), pt.work(t);

    // for (int i = 0; i < ps.size(); i++) {
    // 	cout << ps.cnt(i) << " " << ps.len(i) << "\n";
    // }

    int ans = 0;
    for (int i = 1; i < ps.size(); i++) {
    	ans = (ans + (pt.cnt(i) - ps.cnt(i)) * (pt.cnt(i) - ps.cnt(i)) % mod * ps.len(i) % mod) % mod;
    }
    for (int i = ps.size(); i < pt.size(); i++) {
    	if (pt.len(i) <= n) {
    		ans = (ans + pt.cnt(i) * pt.cnt(i) % mod * pt.len(i) % mod) % mod;
    	}
    }

    cout << ans << "\n";
    return 0;
}

詳細信息

Test #1:

score: 100
Accepted
time: 0ms
memory: 3604kb

input:

5
01010

output:

39

result:

ok 1 number(s): "39"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3796kb

input:

8
66776677

output:

192

result:

ok 1 number(s): "192"

Test #3:

score: 0
Accepted
time: 0ms
memory: 3828kb

input:

1
1

output:

1

result:

ok 1 number(s): "1"

Test #4:

score: 0
Accepted
time: 0ms
memory: 3536kb

input:

2
22

output:

12

result:

ok 1 number(s): "12"

Test #5:

score: 0
Accepted
time: 0ms
memory: 3608kb

input:

2
21

output:

2

result:

ok 1 number(s): "2"

Test #6:

score: 0
Accepted
time: 0ms
memory: 3596kb

input:

3
233

output:

10

result:

ok 1 number(s): "10"

Test #7:

score: 0
Accepted
time: 0ms
memory: 3592kb

input:

3
666

output:

54

result:

ok 1 number(s): "54"

Test #8:

score: 0
Accepted
time: 128ms
memory: 417476kb

input:

1000000
3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333...

output:

496166704

result:

ok 1 number(s): "496166704"

Test #9:

score: -100
Memory Limit Exceeded

input:

3000000
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222...

output:

890701718

result: