poj 3581

来源:互联网 发布:淘宝引流是什么意思 编辑:程序博客网 时间:2024/06/07 05:21

后缀数组  倍增法

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <queue>#define maxn 200010using namespace std;int k, n;int _rank[maxn*2], tem[maxn*2];int sa[maxn*2];int N, A[maxn*2];int rev[maxn*2];bool compare_sa(int i, int j) {    if(_rank[i] != _rank[j]) return _rank[i] < _rank[j];    else {        int ri = i+k <= n ? _rank[i+k] : -1;        int rj = j+k <= n ? _rank[j+k] : -1;        return ri < rj;    }}void construct_sa(int S[], int d) {    n = d;    for(int i = 0; i <= n; ++ i) {        sa[i] = i;        _rank[i] = i < n ? S[i] : -1;    }    for(k = 1; k <= n; k *= 2) {        sort(sa, sa+n+1, compare_sa);        tem[sa[0]] = 0;        for(int i = 1; i <= n; ++ i) {            tem[sa[i]] = tem[sa[i-1]] + (compare_sa(sa[i-1], sa[i]) ? 1 : 0);        }        for(int i = 0; i <= n; ++ i) {            _rank[i] = tem[i];        }    }}void solve() {    reverse_copy(A, A+N, rev);    construct_sa(rev, N);    int p1;    for(int i = 0; i < N; ++ i) {        p1 = N-sa[i];        if(p1 >= 1 && N-p1 >= 2) break;    }    int m = N - p1;    reverse_copy(A+p1, A+N, rev);    reverse_copy(A+p1, A+N, rev+m);    construct_sa(rev, m*2);    int p2;    for(int i = 0; i <= 2*m; ++ i) {        p2 = p1+m-sa[i];        if(p2-p1 >= 1 && N-p2 >= 1) break;    }    reverse(A, A+p1);    reverse(A+p1, A+p2);    reverse(A+p2, A+N);    for(int i = 0; i < N; ++ i) printf("%d\n", A[i]);}int main(){   scanf("%d", &N);    memset(A, 0, sizeof(A));    for(int i = 0; i < N; ++ i) {        scanf("%d", &A[i]);    }    solve();    return 0;}


0 0