BZOJ 1031 后缀数组

1031: [JSOI2007]字符加密Cipher

tags:后缀数组,只要求出sa[]即可。感觉还是直接上模板好,23333

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 2e5+10;

char s[N], str[N];
int wa[N], wb[N], wsf[N], wv[N], sa[N], r[N];

int cmp(int *r, int a, int b, int k)
{
    return r[a]==r[b] && r[a+k]==r[b+k];
}
void getsa(int *r, int *sa, int n, int m)
{
    int i, j, p, *x=wa, *y=wb, *t;
    for(i=0; i<m; i++) wsf[i]=0;
    for(i=0; i<n; i++) wsf[x[i]=r[i]]++;
    for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
    for(i=n-1; i>=0; i--) sa[--wsf[x[i]]]=i;
    for(j=1, p=1; p<n; j*=2, m=p) {
        for(p=0, i=n-j; i<n; i++) y[p++]=i;
        for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
        for(i=0; i<n; i++) wv[i]=x[y[i]];
        for(i=0; i<m; i++) wsf[i]=0;
        for(i=0; i<n; i++) wsf[wv[i]]++;
        for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
        for(i=n-1; i>=0; i--) sa[--wsf[wv[i]]]=y[i];
        for(t=x, x=y, y=t, p=1, x[sa[0]]=0, i=1; i<n; i++)
            x[sa[i]]=cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
    }
}
/*
int height[N], rankn[N];
void getheight(int *r, int *sa, int n)
{
    int i, j, k=0;
    for(i=1; i<=n; i++) rankn[sa[i]]=i;
    for(i=0; i<n; height[rankn[i++]]=k)
        for(k?k--:0, j=sa[rankn[i]-1]; r[i+k]==r[j+k]; k--);
}
*/
int main()
{
    gets(str);
    strcat(s, str);
    strcat(s, str);
    int n=strlen(s), m=0, len=strlen(str);
    s[n]=1;
    rep(i,0,n) {
        r[i]=s[i];
        if(r[i]>m) m=r[i];
    }
    n++;
    getsa(r, sa, n, m+1);
    rep(i,0,n-1) if(sa[i]<len)  printf("%c", s[sa[i]+len-1]);
    puts("");

    return 0;
}
posted @ 2017-02-28 00:35  v9fly  Views(203)  Comments(0Edit  收藏  举报