NSUBSTR - Substrings
Description
You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of times that some string with length x appears in S. For example for string ‘ababa’ F(3) will be 2 because there is a string ‘aba’ that occurs twice. Your task is to output F(i) for every i so that 1<=i<=|S|.
Input
String S consists of at most 250000 lowercase latin letters.
Output
Output |S| lines. On the i-th line output F(i).
Example
Input:
ababa
Output:
3
2
2
1
1
spoj又回归正常了╮(╯▽╰)╭~
然而咱的智商并没有(╯‵□′)╯︵┻━┻
sizeof()打错咱还是头一回……
大触们在发明新方法,而蒟蒻却在发明新错法……
思路:
right数组……
喂这玩意为什么咱以前没有听说过啊啊啊!!!(╯‵□′)╯︵┻━┻
就当是学习了一些人生经验新知识吧~
right数组意义:节点代表的所有的子串的右端点在原串中的位置构成的集合。
那么这个绕口的玩意有什么用呢?
当然有用了,这题的答案就是它的元素个数……
先初始化原串在自动机上跑一边所经过的每一个节点right大小为1。
然后按拓扑序对每个节点传递大小至其父亲,就能求出所有right的大小。
然后用DP跑一边,这题做完了~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=501233;
struct SAM
{
int next[N][26],fa[N],len[N];
int pool,u;
inline void init()
{
pool=u=1;
}
inline void add(int v)
{
int now=++pool;
len[now]=len[u]+1;
while(!next[u][v] && u)
next[u][v]=now,u=fa[u];
if(!u)
fa[now]=1;
else
{
int q=next[u][v];
if(len[q]==len[u]+1)
fa[now]=q;
else
{
int newq=++pool;
memcpy(next[newq],next[q],sizeof(next[q]));//打成sizeof(q)的本蒟蒻智商堪忧......
fa[newq]=fa[q];
len[newq]=len[u]+1;
fa[q]=fa[now]=newq;
while(next[u][v]==q)
next[u][v]=newq,u=fa[u];
}
}
u=now;
}
}koishi;
int sum[N],id[N],r[N];
int f[N];
int main()
{
koishi.init();
char s[N];
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;++i)
koishi.add(s[i]-'a');
int p=1;
for(int i=1;i<=len;++i)
p=koishi.next[p][s[i]-'a'],++r[p];
for(int i=1;i<=koishi.pool;++i)
++sum[koishi.len[i]];
for(int i=1;i<=len;++i)
sum[i]+=sum[i-1];
for(int i=1;i<=koishi.pool;++i)
id[sum[koishi.len[i]]--]=i;
for(int i=koishi.pool;i;--i)
r[koishi.fa[id[i]]]+=r[id[i]];
for(int i=1;i<=koishi.pool;i++)
f[koishi.len[i]]=max(f[koishi.len[i]],r[i]);
for(int i=len;i;i--)
f[i]=max(f[i+1],f[i]);
for(int i=1;i<=len;i++)
printf("%d\n",f[i]);
return 0;
}
本文介绍了一个字符串处理问题NSUBSTR,通过构建后缀自动机(SAM)来高效解决子串频率计算的问题。文章详细展示了如何利用right数组记录子串出现次数,并通过动态规划得出最终答案。
2913

被折叠的 条评论
为什么被折叠?



