SPOJ - 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
F(x)表示S的所有长度为x的子串中,出现次数的最大值,题意为输出F(1),F(2).......F(n).
分析:
从根节点,到主轴上的每个一个节点的数量都赋为数量1,表示根节点到该节点形成的子串数量初始为1(非主轴上的节点是主轴上节点的状态分移出来的,所以初始的时候不赋值,通过后缀链接再赋值)
这样的话,一个节点的后缀链接的num就等于该节点的num+1,对于每个节点,都记录该节点长度出现的子串数量最大值即可
代码如下:
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>

using namespace std;
const int N=250010;
typedef long long ll;
struct State
{
    State *link,*go[26];
    int step;
    int num;
    void clear()
    {
        num=0;
        link=0;
        step=0;
        memset(go,0,sizeof(go));
    }
}*root,*last;
int cnt[N];
int lenA;
State statePool[N*2],*b[N*2],*cur;

void init()
{
    cur=statePool;
    root=last=cur++;
    root->clear();
}

void Insert(int w)
{
    State *p=last;
    State *np=cur++;
    np->clear();
    np->step=p->step+1;
    while(p&&!p->go[w])
        p->go[w]=np,p=p->link;
    if(p==0)
        np->link=root;
    else
    {
        State *q=p->go[w];
        if(p->step+1==q->step)
            np->link=q;
        else
        {
            State *nq=cur++;
            nq->clear();
            memcpy(nq->go,q->go,sizeof(q->go));
            nq->step=p->step+1;
            nq->link=q->link;
            q->link=nq;
            np->link=nq;
            while(p&&p->go[w]==q)
                p->go[w]=nq, p=p->link;
        }
    }
    last=np;
}

void tsort()
{
    memset(cnt,0,sizeof(cnt));
    State *p;
    for(p=statePool;p!=cur;p++)
      cnt[p->step]++;
    for(int i=1;i<=lenA;i++)
      cnt[i]+=cnt[i-1];
    for(p=statePool;p!=cur;p++)
      b[--cnt[p->step]]=p;
}
char A[N],B[N];
int ans[N];
int main()
{
        while(scanf("%s",A)!=EOF){
        init();
        lenA=strlen(A);
        for(int i=0;i<lenA;i++)
         Insert(A[i]-'a');
        tsort();
       memset(ans,0,sizeof(ans));
        State *p;
        p=root;
        for(int i=0;i<lenA;i++)
        {
            int x=A[i]-'a';
           p=p->go[x];
           p->num=1;
        }
       int L=cur-statePool;
       for(int i=L-1;i>0;i--)
       {
           p=b[i];
           ans[p->step]=max(ans[p->step],p->num);
           p->link->num+=p->num;
       }
       for(int i=lenA-1;i>=1;i--)
        ans[i]=max(ans[i],ans[i+1]);
       for(int i=1;i<=lenA;i++)
       {
           printf("%d\n",ans[i]);
       }
        }
    return 0;
}

 

posted @ 2017-10-21 14:00  hinata_hajime  阅读(173)  评论(0编辑  收藏  举报