1. 程式人生 > >[BZOJ2251/BJWC2010]外星聯絡

[BZOJ2251/BJWC2010]外星聯絡

rom clas sort NPU des mes int ati wol

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;
}

[BZOJ2251/BJWC2010]外星聯絡