Life Forms POJ

Life Forms

 POJ - 3294

题意:给出n个字符串,问出现次数大于n/2的最长的子串(如有多个则都要)

用特殊字符连接字符串,后缀数组搞一下.

然后二分长度mid,然后统计次数的时候判断来自哪个字符串,不要重复统计,满足条件就加到答案里去。

高级数据结构p385有更优的,,有空再看

  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]!='';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 }
View Code
原文地址:https://www.cnblogs.com/yijiull/p/7526556.html