题意:小 P 在看过电影《超时空接触》(Contact)之后被深深的打动,决心致力于寻 找外星人的事业。于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星 人发来的信息。虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高 低电平将接收到的信号改写为由 0 和 1 构成的串, 并坚信外星人的信息就隐藏在 其中。他认为,外星人发来的信息一定会在他接受到的 01 串中重复出现,所以 他希望找到他接受到的 01 串中所有重复出现次数大于 1 的子串。但是他收到的 信号串实在是太长了,于是,他希望你能编一个程序来帮助他。
思路:后缀数组
求出height,从前往后扫
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 using namespace std; 6 #define MAXN 6100 7 int n; 8 char a[MAXN]; 9 int tmp[MAXN],cnt[MAXN],suffix_array[MAXN],rank[MAXN],oldrank[MAXN],memo[2],height[MAXN]; 10 bool use[MAXN/2][MAXN/2]; 11 void make_suffix_array() 12 { 13 memo[0]=memo[1]=0; 14 memset(rank,0,sizeof(rank)); 15 memset(oldrank,0,sizeof(oldrank)); 16 int i,l; 17 for(i=1;i<=n;i++) memo[a[i]]=1; 18 memo[1]+=memo[0]; 19 for(i=1;i<=n;i++) rank[i]=memo[a[i]]; 20 for(l=1;l<=n;l*=2) 21 {
22 memset(cnt,0,sizeof(cnt)); 23 for(i=1;i<=n;i++) cnt[rank[i+l]]++; 24 for(i=1;i<=n;i++) cnt[i]+=cnt[i-1]; 25 for(i=n;i>0;i--) tmp[cnt[rank[i+l]]--]=i; 26 27 memset(cnt,0,sizeof(cnt)); 28 for(i=1;i<=n;i++) cnt[rank[tmp[i]]]++; 29 for(i=1;i<=n;i++) cnt[i]+=cnt[i-1]; 30 for(i=n;i>0;i--) suffix_array[cnt[rank[tmp[i]]]--]=tmp[i]; 31 32 memcpy(oldrank,rank,sizeof(rank)); 33 rank[suffix_array[1]]=1; 34 int k=1; 35 for(i=2;i<=n;i++) 36 { 37 int x=suffix_array[i],y=suffix_array[i-1]; 38 if(oldrank[x]!=oldrank[y]||oldrank[x+l]!=oldrank[y+l]) k++; 39 rank[x]=k; 40 } 41 if(k==n) break; 42 } 43 } 44 void LCP() 45 { 46 int i,j,k=0; 47 a[n+1]=2; 48 for(i=1;i<=n;i++) 49 { 50 if(rank[i]==n) 51 { 52 height[n]=k=0; continue; 53 } 54 j=suffix_array[rank[i]+1]; 55 k=max(k-1,0); 56 while(a[i+k]==a[j+k]) k++; 57 height[rank[i]]=k; 58 } 59 } 60 void solve() 61 { 62 memset(use,0,sizeof(use)); 63 int i,j,k,ans; 64 for(i=1;i<n;i++) 65 { 66 for(j=1;j<=height[i];j++) 67 if(!use[i][j]&&!use[i+1][j]) 68 { 69 ans=2; 70 use[i][j]=use[i+1][j]=1; 71 for(k=i+1;k<=n;k++) 72 { 73 if(height[k]>=j) 74 ans++,use[k+1][j]=1; 75 else break; 76 } 77 printf("%d\n",ans); 78 } 79 80 } 81 } 82 int main() 83 { 84 scanf("%d",&n); 85 scanf("%s",a); 86 int i; 87 for(i=n;i>0;i--) a[i]=a[i-1]-48; 88 make_suffix_array(); 89 LCP(); 90 solve(); 91 return 0; 92 }