后缀数组(Suffix Array)

#include <cstdio>
#include <cstring>
#include <algorithm>

const int MAXN = 1000005;

namespace SuffixArray {
    int n, sa[MAXN], rank[MAXN], height[MAXN];
    char str[MAXN];

    void buildSA(int m) {
        static int fir[MAXN], sec[MAXN], buc[MAXN], temp[MAXN];
        n = strlen(str);
        str[n++] = 0;

        std::fill(buc, buc + m, 0);
        for (int i = 0; i < n; i++) buc[(int) str[i]]++;
        for (int i = 1; i < m; i++) buc[i] += buc[i - 1];
        for (int i = 0; i < n; i++) rank[i] = buc[(int) str[i]] - 1;

        for (int l = 1; l < n; l <<= 1) {
            for (int i = 0; i < n; i++)
                fir[i] = rank[i], sec[i] = i + l < n ? rank[i + l] : 0;

            std::fill(buc, buc + n, 0);
            for (int i = 0; i < n; i++) buc[sec[i]]++;
            for (int i = 1; i < n; i++) buc[i] += buc[i - 1];
            for (int i = n - 1; ~i; i--) temp[--buc[sec[i]]] = i;

            std::fill(buc, buc + n, 0);
            for (int i = 0; i < n; i++) buc[fir[i]]++;
            for (int i = 1; i < n; i++) buc[i] += buc[i - 1];
            for (int i = n - 1; ~i; i--) sa[--buc[fir[temp[i]]]] = temp[i];

            rank[sa[0]] = 0;
            bool unique = true;
            for (int i = 1; i < n; i++) {
                rank[sa[i]] = rank[sa[i - 1]];
                if (fir[sa[i]] == fir[sa[i - 1]] && sec[sa[i]] == sec[sa[i - 1]])
                    unique = false;
                else rank[sa[i]]++;
            }

            if (unique) break;
        }
    }

    void getHeight() {
        int k = 0;
        for (int i = 0; i < n - 1; i++) {
            k ? k-- : 0;
            int j = sa[rank[i] - 1];
            while (str[i + k] == str[j + k]) k++;
            height[rank[i]] = k;
        }
    }
}

int main() {
    char *str = SuffixArray::str;
    scanf("%s", str);

    SuffixArray::buildSA(128);
    int *sa = SuffixArray::sa, n = SuffixArray::n;
    for (int i = 1; i < n; i++) printf("%d%c", sa[i] + 1, " \n"[i == n - 1]);

    SuffixArray::getHeight();
    int *height = SuffixArray::height + 1;
    for (int i = 1; i < n - 1; i++) printf("%d%c", height[i], " \n"[i == n - 2]);

    return 0;
}

results matching ""

    No results matching ""