bzoj1031: [JSOI2007]字符加密Cipher(后缀数组)

1031: [JSOI2007]字符加密Cipher

题目:传送门

正解:

   后缀数组裸题。。。

   刚开始看的时候可能觉得一个个排序很麻烦,其实在后面接多一个相同的字符串之后再跑一边sa就ok

   因为对于每一个组成顺序不同的字符串来说,其实长度都是一样的,这就保证了他们在这个长度的范围内就可以比较出大小。

   所以我们所做的预处理是没有影响的。

   输出的时候再稍微判断一下就AC了...有点水

手撸模版:

   

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define N 1100000
 7 using namespace std;
 8 int Rank[N],Rsort[N],sa[N],y[N],wr[N];
 9 char s[N];
10 int a[N];
11 int len,n;
12 bool cmp(int k1,int k2,int ln){return wr[k1]==wr[k2] && wr[k1+ln]==wr[k2+ln];}
13 void get_sa(int n,int m)
14 {
15     memcpy(Rank,a,sizeof(Rank));
16     
17     memset(Rsort,0,sizeof(Rsort));
18     for(int i=1;i<=n;i++)Rsort[Rank[i]]++;
19     for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1];
20     for(int i=n;i>=1;i--)sa[Rsort[Rank[i]]--]=i;
21     
22     int ln=1,k,p=0;
23     while(p<n)
24     {
25         k=0;
26         for(int i=n-ln+1;i<=n;i++)y[++k]=i;
27         for(int i=1;i<=n;i++)if(sa[i]>ln)y[++k]=sa[i]-ln;
28         
29         for(int i=1;i<=n;i++)wr[i]=Rank[y[i]];
30         
31         memset(Rsort,0,sizeof(Rsort));
32         for(int i=1;i<=n;i++)Rsort[wr[i]]++;
33         for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1];
34         for(int i=n;i>=1;i--)sa[Rsort[wr[i]]--]=y[i];
35         
36         for(int i=1;i<=n;i++)wr[i]=Rank[i];
37         p=1;Rank[sa[1]]=1;
38         for(int i=2;i<=n;i++)
39         {
40             if(!cmp(sa[i],sa[i-1],ln))p++;
41             Rank[sa[i]]=p;
42         }
43         m=p;ln*=2;
44     }
45 }
46 int main()
47 {
48     scanf("%s",s+1);len=strlen(s+1);
49     n=len*2;int j=0;
50     for(int i=len+1;i<=n;i++)s[i]=s[++j];
51     for(int i=1;i<=n;i++)a[i]=s[i];
52     get_sa(n,1000);
53     for(int i=1;i<=n;i++)
54     {
55         if(sa[i]>len)continue;
56         else
57         {
58             printf("%c",a[sa[i]+len-1]);
59         }
60     }
61     printf("
");
62     return 0;
63 }
原文地址:https://www.cnblogs.com/CHerish_OI/p/8042650.html