[bzoj1031][JSOI2007]字符加密Cipher
显然把原串复制一遍,然后排序长度为len的各个后缀就行了。
我只是突然想试试hash。。。代码量不到1k而且似乎竟然比写得不是很好的后缀数组快?自然溢出大法好...
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ui unsigned int 6 using namespace std; 7 const int maxn=100233; 8 ui pre[maxn<<1],jc[maxn]; 9 int a[maxn]; 10 char s[maxn<<1]; 11 int i,j,k,n,m; 12 13 inline int smlen(int a,int b){ 14 register int l=1,r=n,mid;a--,b--; 15 if(pre[a+r]-pre[a]*jc[n]==pre[b+r]-pre[b]*jc[n])return n;else r--; 16 while(l<r){ 17 mid=(l+r+1)>>1; 18 if(pre[a+mid]-pre[a]*jc[mid]==pre[b+mid]-pre[b]*jc[mid])l=mid;else r=mid-1; 19 } 20 return l; 21 } 22 bool cmp(int a,int b){ 23 if(s[a]!=s[b])return s[a]<s[b]; 24 int x=smlen(a,b); 25 return x<n?s[a+x]<s[b+x]:0; 26 } 27 28 int main(){ 29 scanf("%s",s);n=strlen(s),m=n<<1; 30 for(i=n;i;i--)s[i]=s[i-1]; 31 for(i=n+1;i<=m;i++)s[i]=s[i-n]; 32 33 for(i=1;i<=m;i++)pre[i]=pre[i-1]*(ui)259+(ui)s[i]; 34 for(i=jc[0]=1;i<=n;i++)a[i]=i,jc[i]=jc[i-1]*(ui)259; 35 sort(a+1,a+1+n,cmp); 36 for(i=1;i<=n;i++)putchar(s[a[i]+n-1]);puts(""); 37 return 0; 38 }