Cod sursa(job #141178)

Utilizator SycronVene Tian Sycron Data 22 februarie 2008 20:19:25
Problema Substr Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.61 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;   
}