Topic: Given a string, each time the head or tail in a new string, the dictionary order the smallest new string
First, if the characters on both sides are different then be sure to choose the small one in the new string.
But if the two sides are the same, for example, CCBACC must be better off from the tail because CCA is smaller than CCB.
So we turn the original string back into [email protected] and then run the suffix array each time you can compare the size of the two substrings with the O (1)
Time complexity O (NLOGN)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 60600using namespace Std;int n;char s[m];int x[m],y[m],sa[m],rank[m];int sum[m],cnt[m],temp[m],tot;inline Char Get_ char () {char c;do c=getchar (); while (c== ' | | c== ' \ t ' | | c== ' \ n ' | | c== ' \ R '); return c;} void Get_rank () {int i,j;for (i=1;i<=n;i++) sum[s[i]]++;for (i=1;i<=127;i++) sum[i]+=sum[i-1];for (i=1;i<=n;i + +) sa[sum[s[i]-1]+ ++cnt[s[i]]]=i;for (i=1;i<=n;i++) {if (i==1| | S[SA[I]]!=S[SA[I-1]]) ++tot;rank[sa[i]]=tot;}} void Radix_sort (int key[],int order[]) {int i;for (i=0;i<=n;i++) sum[i]=cnt[i]=0;for (i=1;i<=n;i++) sum[key[i]]++ ; for (i=1;i<=n;i++) sum[i]+=sum[i-1];for (i=1;i<=n;i++) temp[sum[key[order[i]]-1]+ ++cnt[key[order[i]]]= Order[i];for (i=1;i<=n;i++) order[i]=temp[i];} void prefix_doubling () {int i,j; Get_rank (); for (j=1;j<=n;j<<=1) {for (i=1;i<=n;i++) {x[i]=rank[i]; Y[i]=i+j>n?0:rank[i+j];sa[i]=i;} Radix_sort (Y,SA); Radix_sort (X,SA); for (i=1,tot=0;i<=n;i++) {if (i==1 | | X[sa[i]]!=x[sa[i-1] | | Y[SA[I]]!=Y[SA[I-1]]) ++tot;rank[sa[i]]=tot;}}} int main () {int i,j=0;cin>>n;s[n+1]= ' A ' -1;for (i=1;i<=n;i++) S[n+1-i]=s[n+1+i]=get_char ();n=n<<1|1; Prefix_doubling (); int L=1,r=n>>1;while (l<=r) {++j;if (S[l]<s[r]) Putchar (s[l++]); else if (S[l]>s[r]) Putchar (s[r--]), else if (Rank[l]<rank[n+1-r]) Putchar (s[l++]), Else Putchar (s[r--]), if (j%80==0) puts ("");}}
Bzoj 1692 Queue transform greedy + suffix array