Cod sursa(job #164214)

Utilizator FlorinC1996Florin C FlorinC1996 Data 23 martie 2008 18:10:12
Problema Substr Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.97 kb
#include <cstdio>   
#include <string.h>   
  
#define Nmax 16500   
#define Lgmax 32   
  
int n, k, niv;   
char sir[Nmax];   
int p[Lgmax][Nmax], c[Nmax], d[Nmax], b[Nmax], inv[Nmax], Q[Nmax], pos[Nmax];   
  
void citire()   
{   
    scanf("%d %d\n", &n, &k);   
    scanf("%s\n", sir);   
}   
  
int lcp(int x, int y)   
{   
    int i, ret = 0;   
  
    if (x == y)   
        return n - x + 1;   
  
    for (i = niv; i >= 0 && x <= n && y <= n; --i)   
       if (p[i][x] == p[i][y])   
       {   
            x += 1 << i;   
            y += 1 << i;   
            ret += 1 << i;   
       }   
  
    return ret;   
}   
  
void solve()   
{   
    int i, put, cnt, next1, next2, sol = 0, st, dr;   
       
    if (k == 1)   
    {   
        printf("%d\n", n);   
        return;   
    }   
       
    for (i = 1; i <= n; ++i)   
        ++c[sir[i - 1]];   
  
    for (i = 1; i <= 255; ++i)   
        c[i] += c[i - 1];   
  
    for (i = n; i >= 1; --i)   
        d[c[sir[i - 1]]--] = i;   
  
    p[0][d[1]] = cnt = 1;   
    for (i = 2; i <= n; ++i)   
    {   
        if (sir[d[i] - 1] != sir[d[i - 1] - 1]) ++cnt;   
        p[0][d[i]] = cnt;   
    }   
  
    for (niv = 1, put = 2; put / 2 < n; ++niv, put <<= 1)   
    {   
        memset(c, 0, sizeof(c));   
        for (i = 1; i <= n; ++i)   
            ++c[i + put / 2 <= n ? p[niv - 1][i + put / 2] : 0];   
        for (i = 1; i <= n; ++i)   
            c[i] += c[i - 1];   
        for (i = n; i >= 1; --i)   
            b[c[i + put / 2 <= n ? p[niv - 1][i + put / 2] : 0]--] = i;   
  
  
        memset(c, 0, sizeof(c));   
        for (i = 1; i <= n; ++i)   
            ++c[p[niv - 1][b[i]]];   
        for (i = 1; i <= n; ++i)   
            c[i] += c[i - 1];   
        for (i = n; i >= 1; --i)   
            d[c[p[niv - 1][b[i]]]--] = b[i];   
  
        p[niv][d[1]] = cnt = 1;   
        for (i = 2; i <= n; ++i)   
        {   
            next1 = d[i] + put / 2 <= n ? p[niv - 1][d[i] + put / 2] : 0;   
            next2 = d[i - 1] + put / 2 <= n ? p[niv - 1][d[i - 1] + put / 2] : 0;   
            if (!(p[niv - 1][d[i]] == p[niv - 1][d[i - 1]] && next1 == next2)) ++cnt;   
            p[niv][d[i]] = cnt;   
        }   
    }   
    --niv, put >>= 1;   
  
    for (i = 1; i <= n; ++i)   
        inv[p[niv][i]] = i;   
       
    for (i = 1; i < n; ++i)   
        b[i] = lcp(inv[i], inv[i + 1]);   
  
    st = dr = 0;   
       
    for (i = 1; i < n; ++i)   
    {   
        while (st <= dr && Q[dr] > b[i])   
            --dr;   
        Q[++dr] = b[i];   
        pos[dr] = i;   
  
        while (i - pos[st] + 1 >= k)   
            ++st;   
  
        if (Q[st] > sol)   
            sol = Q[st];   
    }   
    printf("%d\n", sol);   
}   
  
int main()   
{   
    freopen("substr.in", "r", stdin);   
    freopen("substr.out", "w", stdout);   
    citire();   
    solve();   
    return 0;   
}