SPOJ 8222 Substrings 后缀自动机入门

来源:互联网 发布:radium for mac 编辑:程序博客网 时间:2024/06/11 05:36

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[n].son[c];    }    int getnum() {    return num;    }    int getfa(int n) {    return a[n].fa;    }    int getlen(int n) {    return a[n].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;}