Life Forms POJ - 3294
Life Forms
题意:给出n个字符串,问出现次数大于n/2的最长的子串(如有多个则都要)
用特殊字符连接字符串,后缀数组搞一下.
然后二分长度mid,然后统计次数的时候判断来自哪个字符串,不要重复统计,满足条件就加到答案里去。
高级数据结构p385有更优的,,有空再看
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************************************* 2 > File Name: sa.cpp 3 > Author: yijiull 4 > Mail: 1147161372@qq.com 5 > Created Time: 2017年09月14日 星期四 23时03分53秒 6 ************************************************************************/ 7 //#include<bits/stdc++.h> 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 using namespace std; 12 const int maxn=100105; 13 int len[maxn], sa[maxn], t1[maxn], t2[maxn], c[maxn]; 14 int s[maxn]; 15 char str[maxn]; 16 int h[maxn],rk[maxn]; 17 void build_sa(int n,int m){ 18 int i, *x=t1, *y=t2; 19 for(i = 0; i < m; i++) c[i]=0; 20 for(i = 0; i < n; i++) c[x[i]=s[i]]++; 21 for(i = 1; i < m; i++) c[i]+=c[i-1]; 22 for(i = n-1; i >= 0; i--) sa[--c[x[i]]]=i; 23 for(int k = 1; k <= n; k <<= 1){ 24 int p=0; 25 for(i = n-k; i < n; i++) y[p++]=i; 26 for(i = 0; i < n; i++) if(sa[i]>=k) y[p++]=sa[i]-k; 27 for(i = 0; i < m; i++) c[i]=0; 28 for(i = 0; i < n; i++) c[x[y[i]]]++; 29 for(i = 1; i < m; i++) c[i]+=c[i-1]; 30 for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]]=y[i]; 31 swap(x,y); 32 p=1; 33 x[sa[0]]=0; 34 for(i = 1; i < n; i++) 35 x[sa[i]] = y[sa[i]]==y[sa[i-1]] &&y[sa[i]+k]==y[sa[i-1]+k] ? p-1 : p++; 36 if(p>=n) break; 37 m=p; 38 } 39 } 40 void geth(int n){ 41 for(int i = 0; i <= n; i++) rk[sa[i]]=i; 42 int k=0; 43 for(int i = 0; i < n; i++){ 44 if(k) k--; 45 int j = sa[rk[i]-1]; 46 while(s[i+k]==s[j+k]) k++; 47 h[rk[i]]=k; 48 } 49 } 50 int ans[maxn],vis[110]; 51 int ck(int m,int n,int k){ 52 memset(vis,0,sizeof(vis)); 53 int cnt=0,sz=0; 54 for(int i = 1; i <= n; i++){ 55 if(h[i]>=m){ 56 for(int j = 1; j <= k; j++) { 57 if(sa[i]>len[j-1]&&sa[i]<len[j]) cnt += (!vis[j]) , vis[j]=1; 58 if(sa[i-1]>len[j-1]&&sa[i-1]<len[j]) cnt += (!vis[j]) , vis[j]=1; 59 } 60 }else{ 61 if(cnt>k/2) ans[++sz]=sa[i-1]; 62 cnt=0; 63 memset(vis,0,sizeof(vis)); 64 } 65 } 66 if(cnt>k/2) ans[++sz]=sa[n]; 67 if(sz){ 68 ans[0]=sz; 69 return 1; 70 } 71 return 0; 72 } 73 int main(){ 74 int n; 75 int kase=0; 76 len[0]=-1; 77 while(scanf("%d",&n)!=EOF&&n){ 78 int a=0; 79 ans[0]=0; 80 for(int i = 0; i < n; i++){ 81 scanf("%s",str+a); 82 for(;str[a]!='\0';a++) s[a]=str[a]; 83 s[a]=300+i; 84 len[i+1]=a; 85 a++; 86 } 87 s[a-1]=0; 88 if(kase++) puts(""); 89 build_sa(a,500); 90 geth(a-1); 91 int l=1,r=a; 92 while(l<=r){ 93 int m=(l+r)>>1; 94 if(ck(m,a,n)) l=m+1; 95 else r=m-1; 96 } 97 if(l==1) puts("?"); 98 else{ 99 for(int i = 1; i <= ans[0]; i++){ 100 for(int j = ans[i]; j < ans[i]+l-1; j++){ 101 printf("%c",s[j]); 102 } 103 puts(""); 104 } 105 } 106 } 107 return 0; 108 }