Cod sursa(job #50095)

Utilizator victorsbVictor Rusu victorsb Data 6 aprilie 2007 20:47:54
Problema Substr Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.45 kb
#include <cstdio>
#include <string.h>

#define Nmax 16500
#define Lgmax 16

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;

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