比赛 |
20241023 |
评测结果 |
AAAAAAAAAAAAAAA |
题目名称 |
The 'Winning' Gene |
最终得分 |
100 |
用户昵称 |
darkMoon |
运行时间 |
5.566 s |
代码语言 |
C++ |
内存使用 |
25.00 MiB |
提交时间 |
2024-10-23 10:11:58 |
显示代码纯文本
#include<bits/stdc++.h>
using namespace std;
auto IN = freopen("winninggene.in", "r", stdin);
auto OUT = freopen("winninggene.out", "w", stdout);
auto mread = [](){int x;scanf("%d", &x);return x;};
const int N = 3005, p = 127, MOD = 998244353;
int n = mread(), sum[N][N], ha[N][20], pw[N], ans[N], l[N], r[N];
char s[N];
int bal(int x, int y, int l){
// 比较以 x 和 y 开头的两个长度为 l 的字符串
// return -> -1: x > y 0: x = y 1: x < y
int sum = 0;
for(int i = __lg(l); i >= 0; i --){
if(sum + (1 << i) <= l && ha[x][i] == ha[y][i]){
x += 1 << i;
y += 1 << i;
sum += 1 << i;
}
}
if(sum == l){
return 0;
}
else if(s[x] > s[y]){
return -1;
}
else{
return 1;
}
}
signed main(){
pw[0] = 1;
for(int i = 1; i < N; i ++){
pw[i] = pw[i - 1] * p % MOD;
}
scanf("%s", s + 1);
for(int i = 1; i <= n; i ++){
ha[i][0] = (s[i] - '0' + 1);
}
for(int j = 1; j <= 15; j ++){
for(int i = 1; i <= n - (1 << j) + 1; i ++){
ha[i][j] = (1ll * ha[i][j - 1] * pw[1 << j - 1] % MOD + ha[i + (1 << j - 1)][j - 1]) % MOD;
}
}
stack<int> st;
for(int i = 1; i <= n; i ++){
// L 的值为 i,也就是胜利基因候选(小子串)的长度为 i
while(st.size()){
st.pop();
}
// 单调栈,作用是找出左边第一个字典序 小于等于 当前字符串的
for(int j = 1; j <= n - i + 1; j ++){
// L 是从 j 开始的,也就是 L = [j, j + i - 1]
while(st.size()){
int tmp = bal(st.top(), j, i);
if(tmp == -1){
st.pop();
}
else{
break;
}
}
if(st.size() == 0){
l[j] = 0;
}
else{
l[j] = st.top();
}
st.push(j);
}
while(st.size()){
st.pop();
}
// 单调栈,作用是找出右面第一个字典序 小于 当前字符串的
for(int j = n - i + 1; j >= 1; j --){
// L 是从 j 开始的,也就是 L = [j, j + i - 1]
while(st.size()){
int tmp = bal(j, st.top(), i);
if(tmp == 1 || tmp == 0){
st.pop();
}
else{
break;
}
}
if(st.size() == 0){
r[j] = n + 1;
}
else{
r[j] = st.top() + i - 1;
}
st.push(j);
}
for(int j = 1; j <= n - i + 1; j ++){
sum[i][i] ++;
sum[i][r[j] - l[j] - 1 + 1] --;
}
}
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
sum[i][j] += sum[i][j - 1];
ans[sum[i][j]] ++;
}
}
for(int i = 1; i <= n; i ++){
printf("%d\n", ans[i]);
}
return 0;
}