Cod sursa(job #1618871)

Utilizator algebristulFilip Berila algebristul Data 28 februarie 2016 01:23:42
Problema Substr Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.85 kb
#include <cstdio>
#include <algorithm>

using namespace std;

const int nmax = 16386;

struct sa_node {
    int posa;
    int posb;
    int idx;

    inline bool operator<(const sa_node& other) const {
        if (posa == other.posa) {
            return posb < other.posb;
        }
        return posa < other.posa;
    }
};

int n, k, step, cnt, ans = 0;
char s[nmax];
int suffix[nmax];
int sa[15][nmax];
sa_node nodes[nmax];

void build_sa() {
    for (int i = 1; i <= n; i++) {
        sa[0][i] = s[i];
    }

    for (step = cnt = 1; cnt <= n; step++, cnt *= 2) {
        for (int i = 1; i <= n; i++) {
            nodes[i].idx = i;
            nodes[i].posa = sa[step - 1][i];
            if (i + cnt <= n)
                nodes[i].posb = sa[step - 1][i + cnt];
            else
                nodes[i].posb = -1;
        }

        sort(nodes + 1, nodes + n + 1);

        for (int i = 1; i <= n; i++) {
            if (nodes[i].posa == nodes[i-1].posa && nodes[i].posb == nodes[i-1].posb)
                sa[step][nodes[i].idx] = sa[step][nodes[i-1].idx];
            else
                sa[step][nodes[i].idx] = i;
        }
    }
}

int lcp(int x, int y) {
    if (x == y)
        return n - x + 1;

    int ret = 0;

    for (int k = step - 1; k >= 0 && x <= n && y <= n; k--) {
        if (sa[k][x] == sa[k][y]) {
            ret += 1<<k;
            x += 1<<k;
            y += 1<<k;
        }
    }

    return ret;
}

int main() {
    freopen("substr.in", "r", stdin);
    freopen("substr.out", "w", stdout);

    scanf("%d %d", &n, &k);

    scanf("%s", s+1);

    build_sa();

    for (int i = 1; i <= n; i++)
        suffix[sa[step - 1][i]] = i;

    for (int i = 1; i <= n - k + 1; i++) {
        ans = max(ans, lcp(suffix[i], suffix[i + k - 1]));
    }

    printf("%d\n", ans);
}