BZOJ1031[JSOI2007]字符加密Cipher 后缀数组

来源:互联网 发布:手机数据联网控制软件 编辑:程序博客网 时间:2024/06/05 13:25

一万年没打过SA。。
对于原串复制一遍,然后对于每个i<=n的,输出一下他的末尾就好了。

#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=2e5+5;char s[N];int sa[N],n;int sum[N],rank[N],nrank[N],nsa[N];inline void sort(int j){    memset(sum,0,sizeof(sum));    fo(i,1,n)sum[rank[i+j]]++;    fo(i,1,n)sum[i]+=sum[i-1];    fd(i,n,1)nsa[sum[rank[i+j]]--]=i;    memset(sum,0,sizeof(sum));    fo(i,1,n)sum[rank[i]]++;    fo(i,1,n)sum[i]+=sum[i-1];    fd(i,n,1)sa[sum[rank[nsa[i]]]--]=nsa[i];}inline void getsa(){    memset(sum,0,sizeof(sum));    fo(i,1,n)rank[i]=s[i];    fo(i,1,n)sum[rank[i]]++;    fo(i,1,255)sum[i]+=sum[i-1];    fd(i,n,1)    sa[sum[rank[i]]--]=i;    nrank[sa[1]]=1;    int p=1;    fo(i,2,n)    nrank[sa[i]]=rank[sa[i]]==rank[sa[i-1]]?p:++p;    fo(i,1,n)rank[i]=nrank[i];    for(int j=1;j<=n;j<<=1)    {        sort(j);        nrank[sa[1]]=1;        p=1;        fo(i,2,n)        {            if (rank[sa[i]]!=rank[sa[i-1]]||rank[sa[i]+j]!=rank[sa[i-1]+j])p++;            nrank[sa[i]]=p;        }        fo(i,1,n)rank[i]=nrank[i];    }    return;}int main(){    scanf("%s",s+1);    n=strlen(s+1);    fo(i,1,n)s[i+n]=s[i];    n*=2;    getsa();    fo(i,1,n)if (sa[i]<=n/2)    printf("%c",s[sa[i]+n/2-1]);    printf("\n");    return 0;}
0 0