您的位置:首页 > 其它

SPOJ 8222 Substrings 后缀自动机入门

2017-10-18 22:34 441 查看


NSUBSTR - Substrings

#suffix-array-8

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


 Submit
solution!

题意:求一个字符串当中,长度为1,2..len的子串最多出现多少次。

根据字符串构造后缀自动机。

我们在每个节点上已经得到的最长的长度maxlen,则只要求出这个点的|right|,去更新ans[1...maxlen]就好了。实际上,只需要更新ans[maxlen],再O(n)的从长度较长的答案向长度小的答案更新。

而对于每个点的|right|,我们先把原串在自动机上跑一遍,把跑到的节点都设为1,其余设为0.之后,根据拓扑排序的关系从后向前推,即可获得每个点的|right|值。

#include <cstdio>
#include <iostream>
#include <string.h>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=250005,maxk=26,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
int dp[maxn*2],f[maxn*2],w[maxn*2],r[maxn*2];
char s[maxn];

class SAM {
public:
void init() {
num=last=0;
a[0].len=0;a[0].fa=-1;
for (int i=0;i<maxk;i++) a[0].son[i]=-1;
}
void update (int c) {
int now=++num,p;
a[now].len=a[last].len+1;
memset(a[now].son,-1,sizeof(a[now].son));
for (p=last;p!=-1&&a[p].son[c]==-1;p=a[p].fa)
a[p].son[c]=now;
if (p==-1) a[now].fa=0; else {
int q=a[p].son[c];
if (a[p].len+1==a[q].len) {
a[now].fa=q;
} else {
int ne=++num;
a[ne].len=a[p].len+1;
memcpy(a[ne].son,a[q].son,sizeof(a[q].son));
a[ne].fa=a[q].fa;
for (;p!=-1&&a[p].son[c]==q;p=a[p].fa)
a[p].son[c]=ne;
a[q].fa=a[now].fa=ne;
}
}
last=now;
}
int getson(int n,int c) {
return a
.son[c];
}
int getnum() {
return num;
}
int getfa(int n) {
return a
.fa;
}
int getlen(int n) {
return a
.len;
}
private:
int num,last;
struct node{
int len,fa;
int son[maxk];
} a[maxn*2];
};
SAM sa;

int main() {
int n,m,len,i,j;
scanf("%s",s);
len=strlen(s);
sa.init();
for (i=0;i<len;i++) {
sa.update(s[i]-'a');
}
mem0(dp);
int now=0;
m=sa.getnum();
/* for(i=0;i<=m;i++) {
cout << sa.getfa(i) << endl;
}*/
for (i=0;i<len;i++) {
now=sa.getson(now,s[i]-'a');
dp[now]++;
}
mem0(w);
for(i=0;i<=m;i++) w[sa.getlen(i)]++;
for(i=0;i<=len;i++) w[i]+=w[i-1];
for(i=m;i>=0;i--) r[--w[sa.getlen(i)]]=i;
for (i=m;i>0;i--) {
int to=sa.getfa(r[i]);
if (to!=-1) dp[to]+=dp[r[i]];
}
mem0(f);
for (i=1;i<=m;i++) {
int p=sa.getlen(i);
f[p]=max(f[p],dp[i]);
}
for (i=len-1;i>=1;i--) f[i]=max(f[i],f[i+1]);
for (i=1;i<=len;i++) printf("%d\n",f[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: