【刷题】SPOJ 8222 NSUBSTR - Substrings

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

Solution

当 SAM模板题做,建出SAM后,对于一个状态,它的子树size和就是它代表的子串出现次数

然后由于SAM是最简状态自动机,所以有时不一定所有子串都有自己的状态

但是如果一个长度为 \(l\) 的子串出现了 \(k\) 次,那么长度为 \(l-1\) 的子串至少也出现了 \(k\)

利用这点,最后再一个循环搞定答案

这里用的基数排序求拓扑序,避免了写dfs,舒服很多

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=250000+10;
int las=1,tot=1,size[MAXN<<1],ch[MAXN<<1][30],fa[MAXN<<1],len[MAXN<<1],n,cnt[MAXN],rk[MAXN<<1],ans[MAXN];
char s[MAXN];
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void extend(int c)
{
	int p=las,np=++tot;
	las=np;
	len[np]=len[p]+1;
	while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
	if(!p)fa[np]=1;
	else
	{
		int q=ch[p][c];
		if(len[q]==len[p]+1)fa[np]=q;
		else
		{
			int nq=++tot;
			fa[nq]=fa[q];
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			len[nq]=len[p]+1,fa[q]=fa[np]=nq;
			while(p&&ch[p][c]==q)ch[p][c]=nq,p=fa[p];
		}
	}
	size[np]=1;
}
int main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	for(register int i=1;i<=n;++i)extend(s[i]-'a'+1);
	for(register int i=1;i<=tot;++i)cnt[len[i]]++;
	for(register int i=1;i<=n;++i)cnt[i]+=cnt[i-1];
	for(register int i=1;i<=tot;++i)rk[cnt[len[i]]--]=i;
	for(register int i=tot;i>=1;--i)size[fa[rk[i]]]+=size[rk[i]],chkmax(ans[len[rk[i]]],size[rk[i]]);
	for(register int i=n;i>=1;--i)chkmax(ans[i],ans[i+1]);
	for(register int i=1;i<=n;++i)write(ans[i],'\n');
	return 0;
}
posted @ 2018-05-28 15:15  HYJ_cnyali  阅读(138)  评论(0编辑  收藏  举报