码迷,mamicode.com
首页 > 其他好文 > 详细

UVa11107 Lifeform

时间:2016-05-07 10:04:12      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:

题目链接

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

UVa11107 Lifeform

标签:

原文地址:http://blog.csdn.net/qwsin/article/details/51332751

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!