后缀数组(模板)

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#define N 30000
using namespace std;
int a[N + 5],n,k,sa[2][N + 5],v[N + 5],rank[2][N + 5],h[N + 5];
char s[N + 5];
bool p,q;
inline void init(){
    scanf("%d",&n);
    scanf("%s",s + 1);
    for (int i = 1;i <= n; ++i) a[i] = (int)(s[i]) - 96;
}

inline void calsa(int sa[N + 5],int rank[N + 5],int SA[N + 5],int Rank[N + 5]){
    for (int i = 1;i <= n; ++i) v[rank[sa[i]]] = i;
    for (int i = n; i >= 1; --i)
      if (sa[i] > k) 
       SA[v[rank[sa[i] - k]]--] = sa[i] - k; 
     for (int i = n - k + 1;i <= n; ++i)
        SA[v[rank[i]]--] = i;
    for (int i = 1;i <= n; ++i)
     Rank[SA[i]] = Rank[SA[i - 1]] + (rank[SA[i]] != rank[SA[i - 1]]||rank[SA[i] + k] != rank[SA[i - 1] + k ]);
}

inline void DO_IT(){
     p = 0,q = 1;
    for (int i = 1;i <= n; ++i) v[a[i]]++;
    for (int i = 1;i <= 26; ++i) v[i] += v[i - 1];
    for (int i = 1;i <= n; ++i)
      sa[p][v[a[i]]--] = i;
    for (int i = 1;i <= n; ++i)
      rank[p][sa[p][i]] = rank[p][sa[p][i - 1]] + (a[sa[p][i]] != a[sa[p][i - 1]]);
    k = 1;
    while (k < n){
        calsa(sa[p],rank[p],sa[q],rank[q]);
        p ^= 1; q ^= 1; k <<= 1;
    }
    for (int i = 1,k = 0;i <= n; ++i){
        int j = sa[p][rank[p][i] - 1];
        while (a[i + k] == a[j + k]) ++k;
        h[rank[p][i]] = k; if (k > 0) --k;
    }
}

inline void print(){
    for (int i = 1;i <= n; ++i) printf("%d\n",sa[p][i]);
}

int main(){
    init();
    DO_IT();
    print();
    return 0;
}

你可能感兴趣的:(后缀数组(模板))