hdu6223(后缀数组)

题意:

  给一个长度为n的字符串s[0..n-1],但i的后继不再是i+1,而是(i*i+1)%n,求所有长度为n的“子串”中,字典序最大的是谁

  n<=150000

分析:

  如果是一般的字符串,那么直接求出后缀数组就行,但现在后继关系发生了变化

  我们在倍增求后缀数组的过程中,只关心某个位置的下个2^k的后继,于是可以先倍增预处理出每个位置的nx[i][j]表示位置i的下个2^j的后继是谁

  时间复杂度O(nlogn)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5;
 4 char s[maxn+50];
 5 int sa[maxn+50],rk[maxn+50];
 6 int t[maxn+50],t2[maxn+50],c[maxn+50];
 7 int nx[maxn+5][19];
 8 int len,k;
 9 queue<int> q[maxn+5];
10 void getsa(int m)//m表示最大字符的编码
11 {
12     memset(t,-1,sizeof(t));
13     memset(t2,-1,sizeof(t2));
14     int *x=t,*y=t2;
15     for(int i=0;i<m;++i) c[i]=0;
16     for(int i=0;i<len;++i) c[x[i]=s[i]]++;
17     for(int i=1;i<m;++i) c[i]+=c[i-1];
18     for(int i=len-1;i>=0;--i) sa[--c[x[i]]]=i;
19     for(int j=0,k=1;k<=len;k<<=1,++j)
20     {
21         /*int p=0;
22         for(int i=len-k;i<len;++i) y[p++]=i;
23         for(int i=0;i<len;++i) if(sa[i]>=k) y[p++]=sa[i]-k;*/
24 
25         int p=0;
26         for(int i=0;i<len;++i) q[nx[i][j]].push(i);
27         for(int i=0;i<len;++i)
28             while(!q[sa[i]].empty())
29             {
30                 y[p++]=q[sa[i]].front();
31                 q[sa[i]].pop();
32             }
33 
34         for(int i=0;i<m;++i) c[i]=0;
35         for(int i=0;i<len;++i) c[x[y[i]]]++;
36         for(int i=0;i<m;++i) c[i]+=c[i-1];
37         for(int i=len-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
38         swap(x,y);
39         p=1,x[sa[0]]=0;
40         for(int i=1;i<len;++i)
41             if(y[sa[i-1]]==y[sa[i]]&&y[nx[sa[i-1]][j]]==y[nx[sa[i]][j]]) x[sa[i]]=p-1;else x[sa[i]]=p++;
42         if(p>=len) break;
43         m=p;
44     }
45 }
46 int main()
47 {
48     int T;
49     scanf("%d",&T);
50     for(int cas=1;cas<=T;++cas)
51     {
52         printf("Case #%d: ",cas);
53         scanf("%d",&len);
54         scanf("%s",s);
55         for(int i=0;i<len;++i) nx[i][0]=(1LL*i*i+1)%len;
56         for(int j=1;j<=18;++j)
57             for(int i=0;i<len;++i) nx[i][j]=nx[nx[i][j-1]][j-1];
58         getsa('9'+1);
59         int pos=sa[len-1];
60         for(int i=1;i<=len;++i,pos=nx[pos][0]) printf("%c",s[pos]);
61         printf("\n");
62     }
63 
64    // for(int i=0;i<n;++i) printf("%d ",sa[i]);printf("\n");
65    // for(int i=0;i<n;++i) printf("%d ",rk[i]);printf("\n");
66    // for(int i=0;i<n;++i) printf("%d ",height[i]);printf("\n");
67     return 0;
68 
69 }
View Code

 

posted @ 2018-05-05 10:33  Chellyutaha  阅读(884)  评论(1编辑  收藏  举报