[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\n",r-i);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Wolfycz/p/10577994.html