poj 3294 Life Forms 后缀数组
2012-02-09 13:39
344 查看
题意:给n个字符串,求一个最长的子串至少出现在[n/2+1]个字符串中
思路:后缀数组 把所有字串连一起,并用不同的字符隔开 二分
P.S. 1. 我的程序C++WA,G++ AC
2. 为什么char的上界是127啊
答案
思路:后缀数组 把所有字串连一起,并用不同的字符隔开 二分
P.S. 1. 我的程序C++WA,G++ AC
2. 为什么char的上界是127啊
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define MAXN 110000 int n,m; int suffix_array[MAXN]; int rank[2*MAXN],oldrank[2*MAXN]; int cnt[MAXN],tmp[MAXN]; int height[MAXN]; int a[MAXN]; int mark[MAXN]; void SuffixArray() { int memo[300]; suffix_array[0]=0; memset(memo,0,sizeof(memo)); memset(rank,0,sizeof(rank)); memset(oldrank,0,sizeof(oldrank)); int i,l; for(i=1;i<=n;i++) memo[a[i]]=1; for(i=1;i<300;i++) memo[i]+=memo[i-1]; for(i=1;i<=n;i++) rank[i]=memo[a[i]]; for(l=1;l<=n;l*=2) { memset(cnt,0,sizeof(cnt)); for(i=1;i<=n;i++) cnt[rank[i+l]]++; for(i=1;i<=n;i++) cnt[i]+=cnt[i-1]; for(i=1;i<=n;i++) tmp[cnt[rank[i+l]]--]=i; memset(cnt,0,sizeof(cnt)); for(i=1;i<=n;i++) cnt[rank[tmp[i]]]++; for(i=1;i<=n;i++) cnt[i]+=cnt[i-1]; for(i=n;i>0;i--) suffix_array[cnt[rank[tmp[i]]]--]=tmp[i]; memcpy(oldrank,rank,sizeof(rank)); rank[suffix_array[1]]=1; int k=1; for(i=2;i<=n;i++) { int x=suffix_array[i-1],y=suffix_array[i]; if(oldrank[x]!=oldrank[y]||oldrank[x+l]!=oldrank[y+l]) k++; rank[y]=k; } if(k==n) break; } } void LCP() { int i,j,k=0; for(i=1;i<=n;i++) { if(rank[i]==n) { height =k=0; continue; } j=suffix_array[rank[i]+1]; k=max(k-1,0); while(a[j+k]==a[i+k]) k++; height[rank[i]]=k; } height[0]=-1; mark[0]=m+1; } bool check(int mid,bool w) { bool use[102]; memset(use,0,sizeof(use)); int k=1; int i,j; for(i=1;i<=n;i++) { if(a[suffix_array[i-1]]>'z') break; if(height[i-1]>=mid) { if(use[mark[suffix_array[i]]]==0) { use[mark[suffix_array[i]]]=1; k++; } } else { if(k>m/2) { if(w==0) return 1; for(j=suffix_array[i-1];j<=suffix_array[i-1]+mid-1;j++) printf("%c",a[j]); printf("\n"); } memset(use,0,sizeof(use)); k=1; use[mark[suffix_array[i]]]=1; } } if(w==0) return 0; printf("\n"); } int binary() { int left=0,right=n+1; int mid; while(left<right) { mid=(left+right)/2; if(check(mid,0)) left=mid; else right=mid; if(right-left==1) return left; } } int main() { char c[1001]; scanf("%d",&m); int i,j,l,k; int maxl; while(m!=0) { memset(a,0,sizeof(a)); j=1; for(i=1;i<=m;i++) { scanf("%s",c); l=strlen(c); for(k=j;k<=l+j-1;k++) { mark[k]=i; a[k]=c[k-j]; } j=j+l; mark[j]=m+1; a[j]='z'+i; j++; } if(m==1) { printf("%s\n\n",c); scanf("%d",&m); continue; } n=j-2; SuffixArray(); LCP(); maxl=binary(); if(maxl!=0) check(maxl,1); else printf("?\n\n"); scanf("%d",&m); } return 0; }
答案
相关文章推荐
- POJ-3294 Life Forms 后缀数组
- POJ3294——Life Forms 后缀数组
- poj3294 Life Forms(后缀数组)
- POJ 3294 Life Forms(后缀数组)
- POJ 3294 Life Forms (后缀数组)
- POJ 3294 Life Forms(后缀数组)
- poj 3294 Life Forms 求n(n>1)个字符串的最长的一个子串 后缀数组
- poj 3294 Life Forms(后缀数组)
- poj 3294 Life Forms (后缀数组)
- poj 3294 Life Forms (后缀数组)
- POJ 3294 Life Forms (后缀数组)
- poj 3294 Life Forms (后缀数组)
- poj 3294 Life Forms (后缀数组应用)
- poj 3294(Life Forms) 2分+ 后缀数组
- POJ 3294 Life Forms(后缀数组)
- POJ 3294 Life Forms(后缀数组)
- POJ 3294 Life Forms 后缀数组
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
- poj 3294 Life Forms(不小于k 个字符串中的最长子串)
- Poj 3294 Life Forms (后缀数组 在n个串中出现k次的最长公共子串并输出)