2251: [2010Beijing Wc] Alien Contact
Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1045 Solved: 644
[Submit][Status][Discuss]
Description
After watching the movie "Contact", Xiao P was deeply moved and determined to devote himself to the cause of
finding aliens. So he crawled on the roof every night trying to listen to
alien . Although what he heard was only some noise, he still
rewritten the received signal into a string of 0s and 1s according to the high and low levels of these noises, and believed that the alien information was hidden in
it. He believes that the information sent by the aliens must be repeated in the 01 string he received, so
he hopes to find all the substrings of the 01 string he has received with a repeating number greater than 1. But the
signal string he received is too long, so he wants you to write a program to help him.
Input
The first line of the input file is an integer N representing the length of the signal string received by P.
The second line of the input file contains a 01 string of length N, which represents the signal string received by little P.
Output
Each line of the output file contains the number of occurrences of a substring with an occurrence greater than 1.
The order of the output is in lexicographical order of the corresponding substrings.
Sample Input
1010101
Sample Output
3
2
2
4
3
3
2
2
HINT
For 100% data, 0 <= N <=3000
Source
We know that all substrings of a character can be represented by the prefix of the suffix, so we first use that set to get the sa and height out
Then we consider essentially different repeated substrings, we enumerate from rank[1] to rank[n], there are different substrings when starting from sa[i] at least until the end of sa[i]+h[i]+1
Then check to see if there are any repetitions
#include <bits/stdc++.h> #define ll long long #define inf 1e9+10 using namespace std; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=1e6+10; int sa[MAXN],h[MAXN],rank[MAXN],n,tmp[MAXN],cnt[MAXN],p[MAXN]; char ch[MAXN]; inline bool equ (int x, int y, int l) { return rank[x]==rank[y]&&rank[x+l]==rank[y+l]; } void build_suffix(){ for(int i=1;i<=n;i++) {sa[i]=i;rank[i]=ch[i]-'0'+1;} for(int i,pos=0,sig=5,l=0;pos<n;sig=pos){ for(i=n-l+1,pos=0;i<=n;i++) p[++pos]=i; for(i=1;i<=n;i++) if(sa[i]>l) p[++pos]=sa[i]-l; for(i=0;i<=sig;i++) cnt[i]=0; for(i=1;i<=n;i++) cnt[rank[i]]++; for(i=1;i<=sig;i++) cnt[i]+=cnt[i-1]; for(i=n;i>=1;i--) sa[cnt[rank[p[i]]]--]=p[i]; for (i = 1, pos = 0; i <= n; i ++) tmp [sa [i]] = equ (sa [i], sa [i-1], l)? pos: ++ pos; for(i=1;i<=n;i++) rank[i]=tmp[i]; l=!l?1:l<<1; } } void build_height(){ for(int i=1,k,j=0;i<=n;i++){ if(!(k=sa[rank[i]-1])) {j=0;continue;} if(j) j--; while(ch[k+j]==ch[i+j]) j++; h[rank[i]]=j; } } int main(){ n=read(); scanf("%s",ch+1); build_suffix(); build_height(); for(int i=1;i<=n;i++){ for(int j=h[i]+1;sa[i]+j-1<=n;j++){ int r; for(r=i+1;r<=n&&h[r]>=j;r++); if(r-i>=2) printf("%d\n",r-i); } } return 0; } /* 7 1010101 */