Life Forms
题意:
求出至少出现在超过一半的字符串中的最长公共子序列。
分析:
和poj3450是一样的题,不过这里搜索到一个满足条件的区间时,不直接跳出,而是拿数组存下来。
代码:

#include <map> #include <queue> #include <math.h> #include <string> #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; #define ll long long #define ull unsigned long long #define cls(x) memset(x,0,sizeof(x)) #define clslow(x) memset(x,-1,sizeof(x)) const int maxm=1000+100; const int maxn=200*maxm; int n,tot,cntp; char s[maxm]; bool vis[maxn]; int r[maxn],block[maxn],pos[maxn]; int sa[maxn],Rank[maxn],height[maxn]; namespace Suffix { int wa[maxn],wb[maxn],wv[maxn],wt[maxn]; int cmp(int *r,int a,int b,int k) { return r[a]==r[b]&&r[a+k]==r[b+k]; } void da(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i=0; i<m; i++) wt[i]=0; for(i=0; i<=n; i++) wt[x[i]=r[i]]++; for(i=1; i<m; i++) wt[i]+=wt[i-1]; for(i=n; i>=0; i--) sa[--wt[x[i]]]=i; p=1; j=1; for(; p<=n; j*=2,m=p) { for(p=0,i=n+1-j; i<=n; i++) y[p++]=i; for(i=0; i<=n; i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0; i<=n; i++) wv[i]=x[y[i]]; for(i=0; i<m; i++) wt[i]=0; for(i=0; i<=n; i++) wt[wv[i]]++; for(i=1; i<m; i++) wt[i]+=wt[i-1]; for(i=n; i>=0; i--) sa[--wt[wv[i]]]=y[i]; t=x; x=y; y=t; x[sa[0]]=0; for(p=1,i=1; i<=n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++; } } void getheight(int *r,int* sa,int n) { int i,j,k=0; for(i=1; i<=n; i++) Rank[sa[i]]=i; for(i=0; i<n; i++) { if(k) k--; else k=0; j=sa[Rank[i]-1]; while(r[i+k]==r[j+k]) k++; height[Rank[i]-1]=k; } } }; bool judge(int len,bool flag) { int cnt=0; for(int j=0;j<=n;j++) vis[j]=false; for(int i=1;i<tot;i++){ if(i<tot-1&&height[i]>=len){ int b1=block[sa[i]],b2=block[sa[i+1]]; if(!vis[b1]) cnt++; vis[b1]=true; if(!vis[b2]) cnt++; vis[b2]=true; } else{ if(cnt>n/2){ if(!flag) return true; else pos[cntp++]=sa[i-1]; } cnt=0; for(int j=0;j<=n;j++) vis[j]=false; } } return false; } int binary_Search() { int ans=-1; int l=1,r=maxm; while(l<=r) { int mid=(l+r)>>1; if(judge(mid,false)){ l=mid+1; ans=mid; } else r=mid-1; } if(ans!=-1) judge(ans,true); return ans; } int main() { // freopen("in.txt","r",stdin); bool flag=false; while(scanf("%d",&n)!=EOF&&n) { tot=0;cntp=0; for(int i=1;i<=n;i++){ scanf("%s",s); int slen=strlen(s); for(int j=0;j<slen;j++){ block[tot]=i; r[tot++]=s[j]-'a'; } r[tot++]=29+i; } r[tot]=0; Suffix::da(r,sa,tot,30+n); Suffix::getheight(r,sa,tot); if(flag) printf(" "); else flag=true; int reval=binary_Search(); if(reval==-1) printf("? "); else{ for(int i=0;i<cntp;i++){ for(int j=pos[i];j<pos[i]+reval;j++){ printf("%c",r[j]+'a'); } printf(" "); } } } return 0; }