[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 }
View Code

 

posted @ 2016-02-10 15:04  czllgzmzl  阅读(196)  评论(0编辑  收藏  举报