BZOJ 1031 [JSOI2007]字符加密Cipher

来源:互联网 发布:淘宝装修生成 编辑:程序博客网 时间:2024/05/29 12:49

把字符串复制一份,接在原串后面,做一遍后缀数组。后缀数组的排名就是原串的排名,就可以直接用啦。

#include<cstdio>#include<cstring>#define MAX 200010using namespace std;char s[MAX];int sa[MAX*2], tsa[MAX*2], rank[MAX*2], trank[MAX*2], sum[MAX*2], n;void fsort(int j){    memset(sum,0,sizeof(sum));    for(int i = 1; i <= n; i++)sum[rank[i+j]]++;    for(int i = 1; i < MAX; i++)sum[i]+=sum[i-1];    for(int i = n; i >= 1; i--)        tsa[sum[rank[i+j]]--]=i;    memset(sum,0,sizeof(sum));    for(int i = 1; i <= n; i++)sum[rank[i]]++;    for(int i = 1; i < MAX; i++)sum[i]+=sum[i-1];    for(int i = n; i >= 1; i--)        sa[sum[rank[tsa[i]]]--]=tsa[i];}void work(){    memset(sum,0,sizeof(sum));    int p;    for(int i = 1; i <= n; i++)trank[i]=int(s[i]);    for(int i = 1; i <= n; i++)sum[trank[i]]++;    for(int i = 1; i < MAX; i++)sum[i]+=sum[i-1];    for(int i = n; i >= 1; i--)        sa[sum[trank[i]]--]=i;    rank[sa[1]]=1;    for(int i = 2, p = 1; i <= n; i++)    {        if(trank[sa[i]]!=trank[sa[i-1]])p++;        rank[sa[i]]=p;    }    for(int j = 1; j <= n; j*=2)    {        fsort(j);        trank[sa[1]]=1;        p=1;        for(int i = 2; i <= n; i++)        {            if(rank[sa[i-1]]!=rank[sa[i]]||rank[sa[i-1]+j]!=rank[sa[i]+j])p++;            trank[sa[i]]=p;         }        for(int i = 1; i <= n ;i++)            rank[i]=trank[i];    }    for(int i = 1; i <= n; i++)        if(sa[i]<=n/2)            printf("%c",s[sa[i]-1]);}int main(){    scanf("%s",s);    s[strlen(s)]=s[0];    n = strlen(s)-1;    for(int i = 1; i <= n; i++)        s[i+n]=s[i];    n<<=1;    work();    return 0;}
1 0
原创粉丝点击