Cod sursa(job #320312)

Utilizator Magnuscont cu nume gresit sau fals Magnus Data 4 iunie 2009 13:34:39
Problema Substr Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.29 kb
#include <cstdio>   
#include <string.h>

int n, k, niv;
char sir[16500];
int p[10][50], c[16500], d[16500], b[16500], inv[16500], Q[16500], pos[16500];

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;
}