접미사 배열 템 플 릿 (두 드 리 기)

5213 단어 접미사 배열
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_n=2e5+5;

int n,m=300,sa[max_n],c[max_n],x[max_n],y[max_n],rank[max_n],height[max_n];
char s[max_n];

inline void build_sa(){
    for (int i=0;i<m;++i) c[i]=0;
    for (int i=0;i<n;++i) c[x[i]=s[i]]++;
    for (int i=1;i<m;++i) c[i]+=c[i-1];
    for (int i=n-1;i>=0;--i) sa[--c[x[i]]]=i;

    for (int k=1;k<=n;k<<=1){
        int p=0;
        for (int i=n-k;i<n;++i) y[p++]=i;
        for (int i=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;

        for (int i=0;i<m;++i) c[i]=0;
        for (int i=0;i<n;++i) c[x[y[i]]]++;
        for (int i=1;i<m;++i) c[i]+=c[i-1];
        for (int i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];

        swap(x,y);
        p=1; x[sa[0]]=0;
        for (int i=1;i<n;++i) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&
                              ((sa[i-1]+k>=n?-1:y[sa[i-1]+k])==(sa[i]+k>=n?-1:y[sa[i]+k]))?p-1:p++;
        if (p>n) break;
        m=p;
    }
}

inline void build_lcp(){
    for (int i=0;i<n;++i) rank[sa[i]]=i;
    height[0]=0;
    int k=0;
    for (int i=0;i<n;++i){
        if (!rank[i]) continue;
        if (k) --k;
        int j=sa[rank[i]-1];
        while (i+k<n&&j+k<n&&s[i+k]==s[j+k]) ++k;
        height[rank[i]]=k;
    }
}

int main(){
    gets(s);
    n=strlen(s);
    build_sa();
    build_lcp();
    for (int i=0;i<n;++i) printf("%d%c",sa[i]+1," 
"
[i==n-1]); for (int i=0;i<n;++i) printf("%d%c",height[i],"
"
[i==n-1]); }

좋은 웹페이지 즐겨찾기