bzoj 1692: [Usaco2007 Dec]队列变换
把序列(串)反过来,连到原串上,然后求一下后缀数组,答案就是每次比较a1,a2(a1初始为1,a2初始为n+1),输出rank小的一个
1 #include<bits/stdc++.h> 2 #define N 100005<<1 3 #define LL long long 4 #define inf 0x3f3f3f3f 5 using namespace std; 6 inline int ra() 7 { 8 int x=0,f=1; char ch=getchar(); 9 while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 10 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 11 return x*f; 12 } 13 int p,q,k,n,a[N],v[N],rank[2][N],sa[2][N]; 14 void cal_sa(int sa[N], int rank[N], int Sa[N], int Rank[N]) 15 { 16 for (int i=1; i<=n; i++) v[rank[sa[i]]]=i; 17 for (int i=n; i>=1; i--) 18 if (sa[i]>k) 19 Sa[v[rank[sa[i]-k]]--]=sa[i]-k; 20 for (int i=n-k+1; i<=n; i++) 21 Sa[v[rank[i]]--]=i; 22 for (int i=1; i<=n; i++) 23 Rank[Sa[i]]=Rank[Sa[i-1]]+(rank[Sa[i-1]]!=rank[Sa[i]] || rank[Sa[i-1]+k]!=rank[Sa[i]+k]); 24 } 25 void work() 26 { 27 p=0,q=1; 28 for (int i=1; i<=n; i++) v[a[i]]++; 29 for (int i=1; i<=30; i++) v[i]+=v[i-1]; 30 for (int i=1; i<=n; i++) sa[p][v[a[i]]--]=i; 31 for (int i=1; i<=n; i++) rank[p][sa[p][i]]=rank[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]); 32 for (k=1; k<n; k<<=1,q^=1,p^=1) cal_sa(sa[p],rank[p],sa[q],rank[q]); 33 } 34 int main() 35 { 36 n=ra(); 37 for (int i=1; i<=n; i++) 38 { 39 char ch[2]; scanf("%s",ch); 40 a[i]=ch[0]-'A'+1; 41 a[n-i+1+n]=a[i]; 42 } 43 n<<=1; 44 work(); 45 int a1=1,a2=n/2+1; 46 for (int i=1; i<=n>>1; i++) 47 { 48 if (rank[p][a1]<rank[p][a2]) printf("%c",(char)a[a1++]+'A'-1); 49 else printf("%c",(char)a[a2++]+'A'-1); 50 if (!(i%80)) cout<<endl; 51 } 52 return 0; 53 }