uoj35: 后缀排序

题目链接
后缀数组模板题。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 100010;

int n, c[N], sa[N];
int rank[N], height[N];
char str[N];

inline void buildSa(int m) {
    int *x = rank, *y = height;
    for (int i = 0; i < m; i++) c[i] = 0;
    for (int i = 0; i < n; i++) c[x[i] = str[i]]++;
    for (int i = 1; i < m; i++) c[i] += c[i - 1];
    for (int i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
    for (int k = 1; k <= n; k <<= 1) {
        int p = 0;
        for (int i = n - k; i < n; i++) y[p++] = i;
        for (int i = 0; i < n; i++) if (sa[i] >= k) y[p++] = sa[i] - k;
        for (int i = 0; i < m; i++) c[i] = 0;
        for (int i = 0; i < n; i++) c[x[y[i]]]++;
        for (int i = 1; i < m; i++) c[i] += c[i - 1];
        for (int i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x, y); x[sa[0]] = 0; p = 1;
        for (int i = 1; i < n; i++)
            x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p - 1 : p++;//这里有点担心越界
        if (p >= n) break;
        m = p;
    }
}
inline void calcHeight() {
    int k = 0;
    for (int i = 0; i < n; i++) rank[sa[i]] = i;
    for (int i = 0; i < n - 1; i++) {
        if (k) k--;
        int j = sa[rank[i] - 1];
        while (str[i + k] == str[j + k]) k++;
        height[rank[i]] = k;
    }
}

int main() {
    scanf("%s", str);
    n = strlen(str);
    for (int i = 0; i < n; i++)
        str[i] -= 'a' - 1;
    str[n++] = 0;//补$不能省略
    buildSa(30);
    calcHeight();
    for (int i = 1; i < n; i++)
        printf("%d ", sa[i] + 1); puts("");
    for (int i = 2; i < n; i++)
        printf("%d ", height[i]); puts("");
    return 0;
}

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32365199/article/details/53992430
文章标签: 后缀数组
个人分类: 算法模板
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

uoj35: 后缀排序

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭