UVa11107 Lifeform

来源:互联网 发布:阴阳师辅助软件ios 编辑:程序博客网 时间:2024/06/14 22:34

题目链接

UVa11107 Lifeform

题解

学了高大上的后缀数组但是还是不怎么会用,关键是版子最开始打错了,害得我必须再重新理解一遍才能找出bug,开始以为是memset(sa,0,sizeof(sa))这句少写了但是并不是这样.话说字符串的题特别容易RE.

这道题二分答案然后后缀数组,先将字符串合并,每个串后加一个奇怪的不相同的字符,二分长度,然后在height数组中去找,每次当当前height值小于ans的时候再开一段,这时检查前一段是否符合要求.具体方法先用一个idx[i]表示字符串中第i个属于第几个字符串然后用flag[i]来表示有没有在第i个字符串中出现,最后统计一下flag==1的个数,若>n/2则return true;复杂度更低的O(n*L)正准备学.

代码

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=100*2+10;const int MAXLEN=10000000*2;int idx[MAXLEN],n;struct SuffixArray{    int s[MAXLEN];    int sa[MAXLEN],height[MAXLEN],rank[MAXLEN],n;    int t[MAXLEN*2],t2[MAXLEN*2];    long long cnt[MAXLEN];    SuffixArray(){n=0;}    void clear(){n=0;}    void build_sa(int m){        int i,*x=t,*y=t2;        for(i=0;i<m;i++) cnt[i]=0;        for(i=0;i<n;i++) cnt[x[i]=s[i]]++;        for(i=1;i<m;i++) cnt[i]+=cnt[i-1];        for(i=n-1;i>=0;i--) sa[--cnt[x[i]]]=i;//血的教训,妈蛋这个等号害了我一整天         for(int k=1,p=0;k<n;k <<=1)        {            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++) cnt[i]=0;            for(i=0;i<n;i++) cnt[x[y[i]]]++;            for(i=1;i<m;i++) cnt[i]+=cnt[i-1];            for(i=n-1;i>=0;i--) sa[--cnt[x[y[i]]]]=y[i];            swap(x,y);            p=1;x[sa[0]]=0;            for(i=1;i<n;i++)              if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])                x[sa[i]]=p-1;              else x[sa[i]]=p++;            if(p>=n)               break;            m=p;        }    }    void build_height()    {        int k=0;        for(int i=0;i<n;i++) rank[sa[i]]=i;        for(int i=0;i<n;i++)        {            if(k) k--;            if(!rank[i]) continue;            int j=sa[rank[i]-1];            while(s[i+k]==s[j+k]) k++;            height[rank[i]]=k;        }    }}SA;inline void add(int ch,int id){    idx[SA.n]=id;    SA.s[SA.n++]=ch;}int flag[maxn];inline int check(int ans){    int check_clock=1;    memset(flag,0,sizeof(flag));    for(int i=1;i<SA.n;i++)    {        if(SA.height[i]>=ans)         {            flag[idx[SA.sa[i]]]=check_clock;            flag[idx[SA.sa[i-1]]]=check_clock;        }        else {            int cnt=0;            for(int j=0;j<n;j++)               if(flag[j]==check_clock) cnt++;            if(cnt>n/2) return true;            flag[idx[SA.sa[i]]]=++check_clock;        }    }    return false;}inline void print_ans(int l,int r){    for(int i=l;i<=r;i++)      printf("%c",SA.s[i]+'a'-1);    printf("\n");}inline void print(int ans){    int check_clock=1;    memset(flag,0,sizeof(flag));    for(int i=1;i<SA.n;i++)    {        if(SA.height[i]>=ans)         {            flag[idx[SA.sa[i]]]=check_clock;            flag[idx[SA.sa[i-1]]]=check_clock;        }        else {            int cnt=0;            for(int j=0;j<n;j++)               if(flag[j]==check_clock) cnt++;            if(cnt>n/2) print_ans(SA.sa[i-1],SA.sa[i-1]+ans-1);            flag[idx[SA.sa[i]]]=++check_clock;        }    }}char s[1000+10];int kase=0;int main(){    int maxlen;    while(scanf("%d",&n)==1&&n)    {        if(kase++) printf("\n");        SA.clear();        maxlen=0;        for(int i=0;i<n;i++){            scanf("%s",s);            int l=strlen(s);            maxlen=max(maxlen,l);            for(int j=0;j<l;j++) add(s[j]-'a'+1,i);            add(100+i,n);        }        if(n==1)         {            printf("%s\n",s);continue;        }        SA.build_sa(101+n);        SA.build_height();        int l=1,r=maxlen,ans=0;        while(l<=r)        {            int mid=((l+r)>>1);            if(check(mid)) ans=mid,l=mid+1;            else r=mid-1;        }        if(ans)print(ans);        else printf("?\n");    }    return 0;}
1 0
原创粉丝点击