QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#620189 | #7876. Cyclic Substrings | wzxtsl# | RE | 0ms | 0kb | C++23 | 4.7kb | 2024-10-07 16:56:59 | 2024-10-07 16:57:01 |
answer
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod= 998244353;
int sum=0;
int lens=0;
//int bronya=0;
struct Node {
int len; // 节点表示的回文子串的长度
int link; // 后缀链接
map<char, int> next; // 从当前节点转移到的节点
int cnt;
// 回文子串出现次数
};
vector<Node> nodes; // 节点数组
int last; // 上一个字符结束的最大回文子串节点
string s; // 构建中的字符串
int k; // 限制的最大回文子串长度
vector<Node> nodes1;
int last1;
string s1; // 构建中的字符串
int k1;
void init(int max_len) {
nodes.push_back({-1, 0, {}, 0}); // root for odd lengths
nodes.push_back({ 0, 0, {}, 0}); // root for even lengths
last = 1;
s.push_back(-1); // -1 是一个虚拟字符,保证边界条件处理
k = max_len;
}
void init1(int max_len) {
nodes1.push_back({-1, 0, {}, 0}); // root for odd lengths
nodes1.push_back({ 0, 0, {}, 0}); // root for even lengths
last1 = 1;
s1.push_back(-1); // -1 是一个虚拟字符,保证边界条件处理
k1 = max_len;
}
void add_letter(char letter) {
//bronya++;
s.push_back(letter);
int cur = s.size() - 1;
int p = last;
while (s[cur - nodes[p].len - 1] != letter) {
p = nodes[p].link;
}
if (nodes[p].next.count(letter)) {
last = nodes[p].next[letter];
nodes[last].cnt++;
return;
}
int new_len = nodes[p].len + 2;
last = nodes.size();
if (new_len > k ) {
last = p; // 更新 last 为当前节点
return; // 不添加超过限制的新节点
}
nodes.push_back({ new_len, 0, {}, 1});
nodes[p].next[letter] = last;
if (nodes[last].len == 1) {
nodes[last].link = 1;
return;
}
p = nodes[p].link;
while (s[cur - nodes[p].len - 1] != letter) {
p = nodes[p].link;
}
nodes[last].link = nodes[p].next[letter];
}
void add_letter1(char letter) {
//bronya++;
s1.push_back(letter);
int cur = s1.size() - 1;
int p = last1;
while (s[cur - nodes1[p].len - 1] != letter) {
p = nodes1[p].link;
}
//cout<<start_idx<<endl;
if (nodes1[p].next.count(letter)) {
last1 = nodes1[p].next[letter];
nodes1[last1].cnt++;
return;
}
int new_len = nodes1[p].len + 2;
last1 = nodes1.size();
if (new_len > k1 ) {
last1 = p; // 更新 last 为当前节点
return; // 不添加超过限制的新节点
}
nodes1.push_back({ new_len, 0, {}, 1, });
nodes1[p].next[letter] = last1;
if (nodes1[last1].len == 1) {
nodes1[last1].link = 1;
return;
}
p = nodes1[p].link;
while (s[cur - nodes1[p].len - 1] != letter) {
p = nodes1[p].link;
}
nodes1[last1].link = nodes1[p].next[letter];
}
void count_all() {
// 从后向前累加每个回文子串的出现次数到其后缀链接
for (int i = nodes.size() - 1; i >= 2; --i) {
nodes[nodes[i].link].cnt += nodes[i].cnt;
}
}
void count_all1() {
// 从后向前累加每个回文子串的出现次数到其后缀链接
for (int i = nodes1.size() - 1; i >= 2; --i) {
nodes1[nodes1[i].link].cnt += nodes1[i].cnt;
}
}
void get_palindromes() {
for (int i = 2; i < nodes.size(); ++i) {
// cout<< nodes[i].cnt<<" "<<nodes1[i].cnt<<endl;
//nodes[i].len <= lens&&nodes[i].start_idx <= lens&&
if (nodes[i].len<=lens&&i<nodes1.size()) {
sum=(sum%mod+nodes[i].len%mod*(nodes[i].cnt-nodes1[i].cnt)%mod*(nodes[i].cnt-nodes1[i].cnt)%mod)%mod;
// cout << "Length: " << nodes[i].len << ", Count: " << nodes[i].cnt << endl;
}
//if (nodes[i].len <= lens&&nodes[i].start_idx <= lens)
else if(nodes[i].len<=lens){
sum=(sum%mod+nodes[i].len%mod*(nodes[i].cnt)%mod*(nodes[i].cnt)%mod)%mod;
// cout << "Length1: " << nodes[i].len << ", Count1: " << nodes[i].cnt << endl;
}
}
cout<<sum<<endl;
}
signed main() {
// k=5;
int n;cin>>n;
string s_input ;cin>>s_input;
string splus=s_input+s_input;
int max_length = n+n;
lens=n;
init(max_length);
for (char c : splus) {
add_letter(c);
}
init1(lens);
for (char c : s_input) {
add_letter1(c);
}
count_all();
count_all1();
get_palindromes();
system("pause");
return 0;
}
//aba abaaba
//abb abbabb
//01010 0101001010
詳細信息
Test #1:
score: 0
Dangerous Syscalls
input:
5 01010
output:
39