2251: [2010Beijing Wc]外星联络
Description
小 P 在看过电影《超时空接触》(Contact)之后被深深的打动,决心致力于寻
找外星人的事业。于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星
人发来的信息。虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高
低电平将接收到的信号改写为由 0 和 1 构成的串, 并坚信外星人的信息就隐藏在
其中。他认为,外星人发来的信息一定会在他接受到的 01 串中重复出现,所以
他希望找到他接受到的 01 串中所有重复出现次数大于 1 的子串。但是他收到的
信号串实在是太长了,于是,他希望你能编一个程序来帮助他。
Input
输入文件的第一行是一个整数N ,代表小 P 接收到的信号串的长度。
输入文件第二行包含一个长度为N 的 01 串,代表小 P 接收到的信号串。
Output
输出文件的每一行包含一个出现次数大于1 的子串所出现的次数。输出的顺
序按对应的子串的字典序排列。
Sample Input
7
1010101
1010101
Sample Output
3
3
2
2
4
3
3
2
2
3
2
2
4
3
3
2
2
HINT
对于 100%的数据,满足 0 <= N <=3000
显然这道题可以用height数组搞一搞。。。
问题是怎么搞。。。
如果一个字符串是以sa[i]开头的,那么会有n-sa[i]-h[i]种不同的字符串。。。
然后就暴力向后面找即可。。。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 10000+5 14 #define maxm 10000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int n,k,a[maxn],sa[maxn],t[maxn],t2[maxn],c[maxm],h[maxn],rk[maxn],b[maxn]; 24 string s; 25 int read(){ 26 int x=0,f=1;char ch=getchar(); 27 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 28 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 29 return x*f; 30 } 31 void getsa(int n,int m) 32 { 33 int *x=t,*y=t2; 34 for0(i,m)c[i]=0; 35 for0(i,n)c[x[i]=a[i]]++; 36 for1(i,m)c[i]+=c[i-1]; 37 for3(i,n,0)sa[--c[x[i]]]=i; 38 for(int k=1;k<=n+1;k<<=1) 39 { 40 int p=0; 41 for2(i,n-k+1,n)y[p++]=i; 42 for0(i,n)if(sa[i]>=k)y[p++]=sa[i]-k; 43 for0(i,m)c[i]=0; 44 for0(i,n)c[x[y[i]]]++; 45 for1(i,m)c[i]+=c[i-1]; 46 for3(i,n,0)sa[--c[x[y[i]]]]=y[i]; 47 swap(x,y);p=1;x[sa[0]]=0; 48 for1(i,n)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p; 49 if(p>=n)break; 50 m=p; 51 } 52 for1(i,n)rk[sa[i]]=i; 53 for(int i=0,k=0,j;i<n;h[rk[i++]]=k) 54 for(k?k--:0,j=sa[rk[i]-1];a[i+k]==a[j+k];k++); 55 } 56 int main(){ 57 //freopen("input.txt","r",stdin); 58 //freopen("output.txt","w",stdout); 59 n=read(); 60 for1(i,n){ 61 char ch=' '; 62 while(ch!='0'&&ch!='1')ch=getchar(); 63 a[i-1]=ch-'0'+1; 64 } 65 a[n]=0; 66 getsa(n,3); 67 for1(i,n-1){ 68 int k=i+1,tot=0; 69 for3(j,n-sa[i],h[i]+1){ 70 while(h[k]>=j)k++; 71 if(k!=i+1)b[++tot]=k-i; 72 } 73 for3(i,tot,1)printf("%d\n",b[i]); 74 } 75 return 0; 76 }