poj 3581 -- 后缀数组

#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
const int N = 2e5 + 10;
int nn,k;
int rank1[N*2];
int temp[N*2];
int a[N];
int sa[N*2];
int rev[N*2];
bool compare_sa(int i,int j)
{
    if(rank1[i] != rank1[j])
        return rank1[i] < rank1[j];
    else
    {
        int ri = i + k <= nn ? rank1[i+k] : -1;
        int rj = j + k <= nn ? rank1[j+k] : -1;
        return ri < rj;
    }
}
void construct_sa(int *S,int n,int *sa)
{
//    int n = S.length();
    for(int i=0;i<=n;i++)
    {
        sa[i] = i;
        rank1[i] = i < n ? S[i] : -1;
    }
    for(k=1;k<=n;k*=2)
    {
        sort(sa,sa+n+1,compare_sa);
        temp[sa[0]] = 0;
        for(int i=1;i<=n;i++)
        {
            temp[sa[i]] = temp[sa[i-1]] + (compare_sa(sa[i-1],sa[i]) ? 1 : 0);
        }
        for(int i=0;i<=n;i++)
        {
            rank1[i] = temp[i];
        }
    }
}
bool contain(string S,int *sa,string T)
{
    int a = 0, b = S.length();
    while(b - a  > 1)
    {
        int c = (a + b) / 2;
        if(S.compare(sa[c],T.length(),T) < 0) a = c;
        else b = c;
    }
    return S.compare(sa[b],T.length(),T) == 0;
}
void solve()
{
    int n;
    cin >> n;
    for(int i=0;i<n;i++)
    {
        cin >> a[i];
    }
    nn = n;
    reverse_copy(a,a+n,rev);
    construct_sa(rev,n,sa);
    //确定第一段的分割位置
    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);
    nn = 2 * m;
    construct_sa(rev,m*2,sa);
    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++)
    {
        cout << a[i] << "\n";
    }
}
int main()
{
    ios::sync_with_stdio(false);
    solve();
    return 0;
}

posted @ 2020-11-01 02:01  hh13579  阅读(50)  评论(1编辑  收藏  举报