POJ 2406

来源:互联网 发布:64位版本的windows 编辑:程序博客网 时间:2024/05/29 19:12


题目链接:http://poj.org/problem?id=2406

题意: 字符串a是由字符串b重复k次得到的,求k的最大值


从小到大枚举字符串b的长度i,当LCP(rank[i],rank[0])==n-i时,就证明a可以由b重复n/i次得到,想象一下

所以我们只要求出所有rank[i]到rank[0]之间的最小值即刻,用RMQ全部预处理的话会超内存


超时的倍增后缀数组

#include <iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#define MAXN 1000005using namespace std;char s[MAXN];int d[MAXN];int sa[MAXN],t1[MAXN],t2[MAXN],c[MAXN],rank[MAXN],height[MAXN],n;void build_sa(int m){    int i,*x=t1,*y=t2;    for(i=0;i<m;i++)c[i]=0;    for(i=0;i<n;i++)c[x[i]=s[i]]++;    for(i=1;i<m;i++)c[i]+=c[i-1];    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;    for(int k=1;k<=n;k<<=1){        int p=0;        for(i=n-k;i<n;i++)y[p++]=i;        for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;        for(i=0;i<m;i++)c[i]=0;        for(i=0;i<n;i++)c[x[y[i]]]++;        for(i=1;i<m;i++)c[i]+=c[i-1];        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];        swap(x,y);        p=1;        x[sa[0]]=0;        for(i=1;i<n;i++)        x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;        if(p>=n)break;        m=p;    }}void calheight(){    int j,k=0;    for(int i=1;i<=n;i++)    rank[sa[i]]=i;    for(int i=0;i<n;height[rank[i++]]=k){        for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++);    }}void LCP(){    int k=rank[0];    d[k]=n;    for(int i=k-1;i>=0;i--){        if(d[i+1]<height[i+1])        d[i]=d[i+1];        else        d[i]=height[i+1];    }    for(int i=k+1;i<=n;i++){        if(d[i-1]<height[i])        d[i]=d[i-1];        else        d[i]=height[i];    }}int solve(){    for(int i=1;i<=n/2;i++){        if(n%i)        continue;        if(d[rank[i]]==n-i)        return n/i;    }    return 1;}int main(){    while(~scanf("%s",s)){        n=strlen(s);        if(s[0]=='.'&&n==1)        break;        s[n]=0;        n++;        build_sa(128);        n--;        calheight();        LCP();        int ans=solve();        printf("%d\n",ans);    }    return 0;}



DC3 算法  AC代码


#include <iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#define MAXN 1000005#define F(x) ((x)/3+((x)%3==1?0:tb))#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)using namespace std;int ss[MAXN*3];char s[MAXN];int d[MAXN];int sa[MAXN*3],rank[MAXN],height[MAXN];int wa[MAXN],wb[MAXN],wv[MAXN],wss[MAXN];int c0(int *r,int a,int b){    return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];}int c12(int k,int *r,int a,int b){    if(k==2)        return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);    else        return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];}void sort(int *r,int *a,int *b,int n,int m){    int i;    for(i=0;i<n;i++) wv[i]=r[a[i]];    for(i=0;i<m;i++) wss[i]=0;    for(i=0;i<n;i++) wss[wv[i]]++;    for(i=1;i<m;i++) wss[i]+=wss[i-1];    for(i=n-1;i>=0;i--) b[--wss[wv[i]]]=a[i];    return;}void dc3(int *r,int *sa,int n,int m){    int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;    r[n]=r[n+1]=0;    for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;    sort(r+2,wa,wb,tbc,m);    sort(r+1,wb,wa,tbc,m);    sort(r,wa,wb,tbc,m);    for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)    rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;    if(p<tbc) dc3(rn,san,tbc,p);    else for(i=0;i<tbc;i++) san[rn[i]]=i;    for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;    if(n%3==1) wb[ta++]=n-1;    sort(r,wb,wa,ta,m);    for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;    for(i=0,j=0,p=0;i<ta && j<tbc;p++)    sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];    for(;i<ta;p++) sa[p]=wa[i++];    for(;j<tbc;p++) sa[p]=wb[j++];    return;}void calheight(int n){    int j,k=0;    for(int i=1;i<=n;i++)    rank[sa[i]]=i;    for(int i=0;i<n;height[rank[i++]]=k){        for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++);    }}void LCP(int n){    int k=rank[0];    d[k]=n;    for(int i=k-1;i>=0;i--){        if(d[i+1]<height[i+1])        d[i]=d[i+1];        else        d[i]=height[i+1];    }    for(int i=k+1;i<=n;i++){        if(d[i-1]<height[i])        d[i]=d[i-1];        else        d[i]=height[i];    }}int solve(int n){    for(int i=1;i<=n/2;i++){        if(n%i)        continue;        if(d[rank[i]]==n-i)        return n/i;    }    return 1;}int main(){    int n;    while(~scanf("%s",s)){        n=strlen(s);        if(s[0]=='.'&&n==1)        break;        for(int i=0;i<n;i++)        ss[i]=s[i]+1;        ss[n]=0;        dc3(ss,sa,n+1,200);        calheight(n);        LCP(n);        int ans=solve(n);        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击