[JSOI2007]字符加密

学了后缀数组 做了后缀数组裸题23333

对于这题来说 只需要把长度为Len的字符串变成长度为2*Len的字符串 跑一遍后缀数组 然后就可以输出结果辣![快乐!]

上代码![板子打得丑QAQ]

 

  1. #include <bits/stdc++.h>  
  2. using namespace std;  
  3. char ss[1000005];  
  4. int c[1000005],Rank[1000005],K,N,M,SA[1000005],Temp[1000005],a[1000005];  
  5. void Build(int x)  
  6. {  
  7.     for (int i=0;i<=x;i++)  
  8.       c[i]=0;  
  9.     for (int i=1;i<=N;i++)  
  10.       c[Rank[Temp[i]]]++;  
  11.     for (int i=1;i<=x;i++)  
  12.       c[i]+=c[i-1];  
  13.     for (int i=N;i>=1;i--)  
  14.       SA[c[Rank[Temp[i]]]--]=Temp[i];  
  15. }  
  16. void BuildSA()  
  17. {  
  18.    for (int i=1;i<=N;i++)  
  19.      Rank[i]=a[i],Temp[i]=i;  
  20.    Build(M=300);  
  21.    for (int T=1;T<N;T*=2)  
  22.      {  
  23.     int p=0;  
  24.     for (int i=N-T+1;i<=N;i++)  
  25.       Temp[++p]=i;  
  26.     for (int i=1;i<=N;i++)  
  27.       if (SA[i]>T)   
  28.         Temp[++p]=SA[i]-T;  
  29.     Build(M=p);  
  30.     swap(Rank,Temp);  
  31.     Rank[SA[1]]=1;  
  32.     p=1;  
  33.     for (int i=2;i<=N;i++)  
  34.         {  
  35.         if (Temp[SA[i]]==Temp[SA[i-1]]&&Temp[SA[i]+T]==Temp[SA[i-1]+T]) Rank[SA[i]]=p;  
  36.         else Rank[SA[i]]=++p;  
  37.         }  
  38.     }  
  39. }  
  40. int main()  
  41. {  
  42.     scanf("%s",ss+1);  
  43.     N=strlen(ss+1);  
  44.     for (int i=1;i<=N;i++)  
  45.     a[i]=ss[i],a[i+N]=a[i],ss[i+N]=ss[i]//把这个字符串复读一遍[]  
  46.     N*=2;  
  47.     BuildSA();  
  48.     for (int i=1;i<=N;i++)  
  49.       if (SA[i]<=(N/2))  
  50.        cout<<ss[SA[i]+N/2-1];  
  51.     return 0;    
  52. }  
原文地址:https://www.cnblogs.com/si--nian/p/10439700.html