Cod sursa(job #66143)

Utilizator victorsbVictor Rusu victorsb Data 16 iunie 2007 01:09:23
Problema Substr Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.52 kb
#include <cstdio>
#include <cstring>

#define Nmax 16500
#define Lg 20

int n, k, niv, put;
char s[Nmax];
int p[Lg][Nmax], c[Nmax], b[Nmax], d[Nmax], inv[Nmax], Q[Nmax], pos[Nmax];

void citire()
{
    scanf("%d %d\n", &n, &k);
    fgets(s, Nmax, stdin);
}

int lcp(int x, int y)
{
	int k, ret = 0;

    if (x == y) return n - x;
    for (k = niv; k >= 0 && x < n && y < n; --k)
    	if (p[k][x] == p[k][y])
        {
            ret += 1 << k;
            x += 1 << k;
            y += 1 << k;
        }

    return ret;
}

void solve()
{
    int i, ct, next1, next2, st, dr, sol = 0;

    if (k == 1)
    {
    	printf("%d\n", n);
        return;
    }
    
    memset(c, 0, sizeof(c));
    for (i = 0; i < n; ++i)
    	++c[s[i]];
    for (i = 1; i <= 255; ++i)
    	c[i] += c[i - 1];

	for (i = n - 1; i >= 0; --i)
        b[--c[s[i]]] = i;

    p[0][b[0]] = ct = 1;
    for (i = 1; i < n; ++i)
    {
        if (s[b[i]] != s[b[i - 1]]) ++ct;
        p[0][b[i]] = ct;
    }

	for (niv = 1, put = 1; put < n; ++niv, put <<= 1)
    {
    	memset(c, 0, sizeof(c));
        for (i = 0; i < n; ++i)
            ++c[i + put < n ? p[niv - 1][i + put] : 0];
        for (i = 1; i <= n; ++i)
        	c[i] += c[i - 1];
        for (i = n - 1; i >= 0; --i)
            b[--c[i + put < n ? p[niv - 1][i + put] : 0]] = i;

        memset(c, 0, sizeof(c));
        for (i = 0; i < n; ++i)
            ++c[p[niv - 1][b[i]]];
        for (i = 1; i <= n; ++i)
        	c[i] += c[i - 1];
        for (i = n - 1; i >= 0; --i)
            d[--c[p[niv - 1][b[i]]]] = b[i];

        p[niv][d[0]] = ct = 1;
        for (i = 1; i < n; ++i)
        {
            next1 = d[i - 1] + put < n ? p[niv - 1][d[i - 1] + put] : 0;
            next2 = d[i] + put < n ? p[niv - 1][d[i] + put] : 0;
            if (!(p[niv - 1][d[i - 1]] == p[niv - 1][d[i]] && next1 == next2)) ++ct;
            p[niv][d[i]] = ct;
        }
    }
    --niv;

    for (i = 0; i < n; ++i)
        inv[p[niv][i]] = i;

    for (i = 1; i < n; ++i)
    	b[i] = lcp(inv[i], inv[i + 1]);

    --n, --k;

    st = 0;
    dr = 0;
    for (i = 1; i <= n; ++i)
    {
    	while (dr >= st && Q[dr] > b[i]) --dr;
        Q[++dr] = b[i];
        pos[dr] = i;
        while (pos[dr] - pos[st] >= k) ++st;
        if (i >= k && 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;
}