Cod sursa(job #114369)

Utilizator sealTudose Vlad seal Data 13 decembrie 2007 22:45:19
Problema Substr Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.25 kb
#include<stdio.h>
#define Nm (1<<14)
#define Lognm 15
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
char S[Nm],Bh[Nm];
int Rmq[Lognm][Nm],Log2[Nm],A[Nm],P[Nm],Bucket[Nm],Cnt[Nm],Lcp[Nm],n,k;

void read()
{
    freopen("substr.in","r",stdin);
    scanf("%d%d%s",&n,&k,S);
}

void suffix_sort()
{
    int i,h,j,s,go_on;

    for(i=0;i<n;++i)
        ++Cnt[S[i]];
    for(i=1;i<256;++i)
        Cnt[i]+=Cnt[i-1];
    for(i=n-1;i>=0;--i)
        A[--Cnt[S[i]]]=i;
        
    for(Bh[0]=i=1;i<n;++i)
    {
        P[A[i]]=i;
        Bh[i]=S[A[i]]!=S[A[i-1]];
    }

    for(go_on=h=1;h<n && go_on;h<<=1)
    {
        for(i=0;i<n;++i)
        {
            if(Bh[i])
                j=i, Cnt[i]=0;
            Bucket[A[i]]=j;
        }

        for(i=0;i<n;++i)
        {
            s=A[i]-h;
            if(s<0)
                continue;
            j=Bucket[s];
            P[s]=j+Cnt[j]++;
        }

        for(i=0;i<n;++i)
            A[P[i]]=i;

        for(go_on=0,i=1;i<n;++i)
        {
            Bh[i]=Bh[i] || A[i]+h==n || Bucket[A[i]+h]!=Bucket[A[i-1]+h];
            if(!Bh[i])
                go_on=1;
        }
    }
}

void compute_lcp()
{
    int i,next,j=0;

    for(i=0;i<n;++i)
    {
        if(P[i]==n-1)
            continue;
        next=A[P[i]+1];
        while(i+j<n && next+j<n && S[i+j]==S[next+j])
            ++j;
        Lcp[P[i]]=j;
        if(j)
            --j;
    }
}

void compute_rmq()
{
    int i,j,cnt;

    for(i=0;i<n-1;++i)
        Rmq[0][i]=Lcp[i];
    for(cnt=2,j=1;cnt<n;++j,cnt<<=1)
        for(i=0;i<n-cnt;++i)
            Rmq[j][i]=min(Rmq[j-1][i],Rmq[j-1][i+(cnt>>1)]);

    Log2[1]=0;
    for(i=2;i<n;++i)
    {
        Log2[i]=Log2[i-1];
        if(1<<Log2[i]+1<=i)
            ++Log2[i];
    }
}

int solve()
{
    int i,j,ans=0;

    if(k==1)
        return n;

    suffix_sort();
    compute_lcp();
    compute_rmq();

    for(i=0;i<=n-k;++i)
    {
        j=Log2[k-1];
        ans=max(ans,min(Rmq[j][i],Rmq[j][i+k-1-(1<<j)]));
    }
    return ans;
}

void write(int ans)
{
    freopen("substr.out","w",stdout);
    printf("%d\n",ans);
}

int main()
{
    read();
    write(solve());
    return 0;
}