卧薪尝胆,厚积薄发。
Substrings
Date: Thu Aug 16 20:51:33 CST 2018 In Category: NoCategory

Description:

$F(x)$ 定义为某些长度 $X$ 的字符串在 $s$ 中出现的最大次数,输出 $F(x),x\in[1,|S|]$ 。
$1\le |S|\le 250000$

Solution:

先像洛谷后缀自动机模板一样统计一下子串出现次数,然后对于统计出结果的每个状态,更新 $F(s[p].maxl)$ ,因为 $F$ 是单调的,所以最后倒推一遍,用 $F(i+1)$ 更新 $F(i)$ 即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXL 250010
char str[MAXL];
struct node
{
int tr[26],par,maxl;
}s[MAXL << 1];
int last = 1,root = 1,ptr = 1;
int newnode(int k){++ptr;s[ptr].maxl = k;return ptr;}
int siz[MAXL << 1];
inline void extend(int k)
{
register int p = last;
register int np = newnode(s[p].maxl + 1);siz[np] = 1;
for(;p && s[p].tr[k] == 0;p = s[p].par)s[p].tr[k] = np;
if(p == 0)s[np].par = root;
else
{
register int q = s[p].tr[k];
if(s[p].maxl + 1 == s[q].maxl)s[np].par = q;
else
{
register int nq = newnode(s[p].maxl + 1);
memcpy(s[nq].tr,s[q].tr,sizeof(s[q].tr));
s[nq].par = s[q].par;
s[q].par = s[np].par = nq;
for(;p && s[p].tr[k] == q;p = s[p].par)s[p].tr[k] = nq;
}
}
last = np;
return;
}
int c[MAXL << 1],a[MAXL << 1];
int f[MAXL];
int main()
{
scanf("%s",str + 1);
register int l = strlen(str + 1);
for(register int i = 1;i <= l;++i)extend(str[i] - 'a');
for(register int i = 1;i <= ptr;++i)c[s[i].maxl]++;
for(register int i = 1;i <= l;++i)c[i] += c[i - 1];
for(register int i = ptr;i >= 1;--i)a[c[s[i].maxl]--] = i;
for(register int i = ptr;i >= 1;--i)
{
siz[s[a[i]].par] += siz[a[i]];
f[s[a[i]].maxl] = max(f[s[a[i]].maxl],siz[a[i]]);
}
for(register int i = l - 1;i >= 1;--i)f[i] = max(f[i],f[i + 1]);
for(register int i = 1;i <= l;++i)printf("%d\n",f[i]);
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡