zoukankan      html  css  js  c++  java
  • [BZOJ2251/BJWC2010]外星联络

    Description
    小 P 在看过电影《超时空接触》(Contact)之后被深深的打动,决心致力于寻找外星人的事业。于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星人发来的信息。虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高低电平将接收到的信号改写为由 0 和 1 构成的串, 并坚信外星人的信息就隐藏在其中。他认为,外星人发来的信息一定会在他接受到的 01 串中重复出现,所以他希望找到他接受到的 01 串中所有重复出现次数大于 1 的子串。但是他收到的信号串实在是太长了,于是,他希望你能编一个程序来帮助他。

    Input
    输入文件的第一行是一个整数N ,代表小 P 接收到的信号串的长度。
    输入文件第二行包含一个长度为N 的 01 串,代表小 P 接收到的信号串。

    Output
    输出文件的每一行包含一个出现次数大于1 的子串所出现的次数。输出的顺
    序按对应的子串的字典序排列。

    Sample Input
    7
    1010101

    Sample Output
    3
    3
    2
    2
    4
    3
    3
    2
    2

    HINT
    对于 100%的数据,满足 0 <= N <=3000


    首先求出Height数组,然后就是暴力枚举长度,判断出现次数是否>1,输出即可

    枚举按照Rank来,就可以保证字典序

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1;char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=3e3;
    bool ck(int *r,int x,int y,int l){return r[x]==r[y]&&r[x+l]==r[y+l];}
    void Suffix_sort(int *A,int *SA,int n,int m){
    	static int sum[N+10],buf[N+10];
    	memset(buf,0,sizeof(buf));
    	int *x=A,*y=buf;
    	for (int i=1;i<=m;i++)	sum[i]=0;
    	for (int i=1;i<=n;i++)	sum[x[i]]++;
    	for (int i=1;i<=m;i++)	sum[i]+=sum[i-1];
    	for (int i=n;i>0;i--)	SA[sum[x[i]]--]=i;
    	for (int l=1,p=0,top=0;p<n;l<<=1,m=p,top=0){
    		for (int i=n-l+1;i<=n;i++)	y[++top]=i;
    		for (int i=1;i<=n;i++)	if (SA[i]>l)	y[++top]=SA[i]-l;
    		for (int i=1;i<=m;i++)	sum[i]=0;
    		for (int i=1;i<=n;i++)	sum[x[y[i]]]++;
    		for (int i=1;i<=m;i++)	sum[i]+=sum[i-1];
    		for (int i=n;i>0;i--)	SA[sum[x[y[i]]]--]=y[i];
    		swap(x,y),x[SA[1]]=p=1;
    		for (int i=2;i<=n;i++)	x[SA[i]]=ck(y,SA[i-1],SA[i],l)?p:++p;
    	}
    }
    int A[N+10],SA[N+10],Rank[N+10],H[N+10];
    void Get_height(char *s,int n){
    	for (int i=1,k=0,j;i<=n;H[Rank[i++]]=k)
    	for (k?k--:0,j=SA[Rank[i]-1];s[i+k]==s[j+k];k++);
    }
    int main(){
    	static char s[N+10];
    	int n=read(),m;
    	scanf("%s",s+1);
    	for (int i=1;i<=n;i++)	A[i]=s[i]-'0'+1;
    	Suffix_sort(A,SA,n,m=2);
    	for (int i=1;i<=n;i++)	Rank[SA[i]]=i;
    	Get_height(s,n);
    	for (int i=1;i<=n;i++){
    		for (int j=H[i]+1,r;SA[i]+j-1<=n;j++){
    			for (r=i+1;r<=n&&H[r]>=j;r++);
    			if (r-i>1)	printf("%d
    ",r-i);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    source insight快捷键及使用技巧
    HTTP 状态码
    select poll epoll三者之间的比较
    服务器程序后台化以及守护进程的编写规范
    Linux 信号表
    Linux下有线无线网络配置------命令模式
    浅谈 qmake 之 pro、pri、prf、prl文件
    Python VUE 基础知识
    VUE 实现tab切换页面效果
    爬虫框架:scrapy
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10577994.html
Copyright © 2011-2022 走看看