字符串hash+排序+二分

字符串hash+排序+二分

\140. 后缀数组

复杂度O(\(n^2log n\))

排序就是题目里的按照字典序把字符串s的所有后缀排序,二分最长公共前缀。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s[300010];
int sa[300010], n;
unsigned long long p[300010], f[300010];
int len(int a, int b) {
    if(s[a] != s[b]) return 0;
    int l = 0, r = n - max(a, b);
    while(l < r) {
        int mid = (l + r + 1) / 2;
        if(f[a+mid] - f[a-1] * p[mid + 1] == f[b+mid] - f[b-1] * p[mid + 1]) {
            l = mid;
        }
        else r = mid - 1;
    }
    return l + 1;
}
bool cmp(int a, int b) {
    int l = len(a, b);
    return s[a+l] < s[b+l];
}
int main() {
    scanf("%s", s+1);
    n = strlen(s+1);
    p[0] = 1;
    for(int i = 1; i <= n; i++) {
        sa[i] = i;
        p[i] = p[i-1] * 131;
        f[i] = f[i-1] * 131 + s[i] - 'a' + 1;
    }
    sort(sa + 1, sa + 1 + n, cmp);
    for(int i = 1; i <= n; i++) {
        printf("%d", sa[i] - 1);
        if(i == n) printf("\n");
        else printf(" ");
    }
    printf("0 ");
    for(int i = 2; i <= n; i++) {
        printf("%d", len(sa[i], sa[i-1]));
        if(i == n) printf("\n");
        else printf(" ");
    }
    return 0;
}

posted @ 2020-04-21 21:09  小饭hhh  阅读(294)  评论(0编辑  收藏  举报