首页 > 编程语言 > 详细

洛谷-P3809-后缀排序(后缀数组)

时间:2019-01-25 22:31:48      阅读:185      评论:0      收藏:0      [点我收藏+]

看了求后缀数组的倍增法之后很快就理解了,但是自己写的倍增法用map排序还是超时了。然后看了两天别人写的模板,题目是通过了,但感觉代码还是半懂半背的。以后多熟悉熟悉吧;

#include "bits/stdc++.h"
using namespace std;
const int MAXN = 1e6 + 5;
char s[MAXN];
int sa[MAXN], rk[MAXN], height[MAXN];
void getSa(char* s, int* sa, int n, int m) {
    int* x = (int*)calloc(MAXN, sizeof(int));
    int* y = (int*)calloc(MAXN, sizeof(int));
    int* cnt = (int*)calloc(MAXN, sizeof(int));
    for (int i = 1; i <= n; i++) {
        cnt[x[i] = s[i]]++;
    }
    for (int i = 2; i <= m; i++) {
        cnt[i] += cnt[i - 1];
    }
    for (int i = n; i; i--) {
        sa[cnt[x[i]]--] = i;
    }
    for (int j = 1; j < n; j <<= 1) {
        int num = 0;
        for (int i = n - j + 1; i <= n; i++) {
            y[++num] = i;
        }
        for (int i = 1; i <= n; i++) {
            if (sa[i] > j) {
                y[++num] = sa[i] - j;
            }
        }
        for (int i = 1; i <= m; i++) {
            cnt[i] = 0;
        }
        for (int i = 1; i <= n; i++) {
            cnt[x[i]]++;
        }
        for (int i = 2; i <= m; i++) {
            cnt[i] += cnt[i - 1];
        }
        for (int i = n; i; i--) {
            sa[cnt[x[y[i]]]--] = y[i];
        }
        swap(x, y);
        x[sa[1]] = num = 1;
        for (int i = 2; i <= n; i++) {
            if (y[sa[i]] != y[sa[i - 1]] || y[sa[i] + j] != y[sa[i - 1] + j]) {
                x[sa[i]] = ++num;
            } else {
                x[sa[i]] = num;
            }
        }
        if (num >= n) {
            break;
        }
        m = num;
    }
    free(x);
    free(y);
    free(cnt);
}
void getHeight(char* s, int* sa, int* rk, int* height, int n) {
    for (int i = 1; i <= n; i++) {
        rk[sa[i]] = i;
    }
    int k = 0;
    for (int i = 1; i <= n; i++) {
        k = k != 0 ? k - 1 : k;
        int j = sa[rk[i] - 1];
        while (s[i + k] == s[j + k]) {
            k++;
        }
        height[rk[i]] = k;
    }
}
int main() {
    gets(s + 1);
    int len = strlen(s + 1);
    getSa(s, sa, len, 130);
    // getHeight(s, sa, rk, height, len);
    for (int i = 1; i < len; i++) {
        printf("%d ", sa[i]);
    }
    printf("%d\n", sa[len]);
    /*
    for (int i = 1; i < len; i++) {
        printf("%d ", rk[i]);
    }
    printf("%d\n", rk[len]);
    for (int i = 1; i < len; i++) {
        printf("%d ", height[i]);
    }
    printf("%d\n", height[len]);
    */
    return 0;
}

附带rank数组和height数组,本题不需要。

洛谷-P3809-后缀排序(后缀数组)

原文:https://www.cnblogs.com/Angel-Demon/p/10321816.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!