poj 3294 Life Forms

来源:互联网 发布:网络迷情金紫阳小说 编辑:程序博客网 时间:2024/05/21 15:03

后缀数组的题目,把后缀连接起来,这个还是先二分答案,然后选取一段连续的height值,判断这些height代表的后缀有没有覆盖一半以上的字符串。

得出答案的长度之后还要在枚举连续的heigh,判断有没有答案,有的话标记其中一个。

最后再按照sa输出答案。这样就可以保证字典序。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn=1e5+10000;int r[maxn];char a[1111];int *rank,height[maxn],sa[maxn];int wx[maxn],wy[maxn],cnt[maxn];int n,m;inline bool cmp(int *r,int a,int b,int l){    return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int *r,int n,int m){    r[n+1]=0;    int i,l,p,*x=wx,*y=wy,*t;    memset(cnt,0,sizeof(int)*(m+1));    for(int i=1;i<=n;i++) cnt[x[i]=r[i]]++;    for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];    for(int i=n;i>=1;i--) sa[cnt[x[i]]--]=i;    for(l=1,p=1;p<n;l<<=1,m=p)    {        for(p=1,i=n-l+1;i<=n;i++) y[p++]=i;        for(i=1;i<=n;i++)        if(sa[i]>l)        y[p++]=sa[i]-l;        memset(cnt,0,sizeof(int)*(m+1));        for(i=1;i<=n;i++) cnt[x[i]]++;        for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];        for(i=n;i>=1;i--) sa[cnt[x[y[i]]]--]=y[i];        for(t=x,x=y,y=t,p=1,x[sa[1]]=1,i=2;i<=n;i++)        x[sa[i]]=cmp(y,sa[i-1],sa[i],l)?p:++p;    }    rank=x;    int j,k=0;for(i=1;i<=n;height[rank[i++]]=k)for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);return;}bool fla[1111];int c[maxn];bool ans[maxn];bool chk(int ret){    for(int i=2;i<=n;i++)    if(height[i]>=ret)    {        int j=i+1;        while(j<=n&&height[j]>=ret) j++;        j--;        memset(fla,0,sizeof(fla));        for(int k=i-1;k<=j;k++)        fla[c[sa[k]]]=1;        int cnt=0;        for(int k=1;k<=m;k++)        cnt+=fla[k];        if(cnt>m/2) return true;        i=j;    }    return false;}int main(){//    freopen("in.txt","r",stdin);    int ret;    int tt=0;    while(scanf("%d",&m),m)    {        if(tt++) printf("\n");        n=0;        for(int i=1;i<=m;i++)        {            scanf("%s",a+1);            ret=strlen(a+1);            for(int j=1;j<=ret;j++)            r[n+j]=a[j];            for(int j=n+1;j<=n+ret;j++)            c[j]=i;            n+=ret;            r[++n]=570+i;        }        da(r,n,680);        int st=0,ed=1111,mid;        while(st<ed)        {            mid=st+ed+1>>1;            if(chk(mid)) st=mid;            else ed=mid-1;        }        if(m==1)        {            for(int i=1;i<n;i++)            printf("%c",r[i]);            printf("\n");        }        else if(st==0)        printf("?\n");        else        {            memset(ans,0,sizeof(ans));            for(int i=1;i<=n;i++)            if(height[i]>=st)            {                int j=i+1;                while(height[j]>=st) j++;                j--;                memset(fla,0,sizeof(fla));                for(int k=i-1;k<=j;k++)                fla[c[sa[k]]]=1;                int cnt=0;                for(int k=1;k<=m;k++)                cnt+=fla[k];                if(cnt>m/2)                {                    ans[sa[i-1]]=1;                }                i=j;            }            for(int i=1;i<=n;i++)            if(ans[sa[i]])            {                for(int j=1;j<=st;j++)                printf("%c",r[j+sa[i]-1]);                printf("\n");            }        }    }    return 0;}


原创粉丝点击