题目大意:
给定n个字符串,求出现在不小于k/2个字符串中的最长子串。
二分找对应子串长度的答案,将所有字符串链接成一个长字符串求后缀数组,记录每一个位置本属于第几个字符串,利用height查询的时候,
根据记录的位置不断判断是否出现重复的字符串是在同一个字符串内的
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <iostream> 5 using namespace std; 6 typedef long long ll; 7 const int N = 200010; 8 int r[N] , sa[N] , rank[N] , height[N]; 9 int K , wa[N] , wb[N] , wv[N] , wsf[N]; 10 int cmp(int *r , int a , int b , int l){return r[a]==r[b]&&r[a+l]==r[b+l];} 11 void da(int *r , int *sa , int n , int m) 12 { 13 int i,j,p,*x=wa,*y=wb,*t; 14 for(i=0;i<m;i++)wsf[i]=0; 15 for(i=0;i<n;i++)wsf[x[i]=r[i]]++; 16 for(i=1 ; i<m ; i++) wsf[i]+=wsf[i-1]; 17 for(i=n-1;i>=0;i--) sa[--wsf[x[i]]]=i; 18 for(j=1,p=1;p<n;j*=2,m=p){ 19 for(p=0,i=n-j;i<n;i++) y[p++]=i; 20 for(i=0;i<n;i++) if(sa[i]>=j)y[p++]=sa[i]-j; 21 for(i=0;i<n;i++) wv[i]=x[y[i]]; 22 for(i=0;i<m;i++) wsf[i]=0; 23 for(i=0;i<n;i++) wsf[wv[i]]++; 24 for(i=1;i<m;i++) wsf[i]+=wsf[i-1]; 25 for(i=n-1;i>=0;i--) sa[--wsf[wv[i]]]=y[i]; 26 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) 27 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 28 } 29 return; 30 } 31 void callHeight(int *r , int *sa , int n) 32 { 33 int i,j,k=0; 34 for(i=1;i<=n;i++) rank[sa[i]]=i; 35 for(i=0;i<n;height[rank[i++]]=k) 36 for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); 37 return; 38 } 39 #define ll long long 40 int n , len , pos[105][2] , dif , mp[N]; 41 bool vis[105]; 42 char s[105][1005] , all[N]; 43 vector<int> ans , tmp; 44 bool check(int mid) 45 { 46 tmp.clear(); 47 bool flag = false; 48 memset(vis , 0 , sizeof(vis)); 49 int cnt = 1 , rec = sa[0]; 50 vis[sa[0]] = true; 51 for(int i=1 ; i<len ; i++){ 52 if(height[i]<mid){ 53 if(cnt>n/2){ 54 tmp.push_back(rec); 55 flag = true; 56 } 57 memset(vis , 0 , sizeof(vis)); 58 cnt = 1 , vis[mp[sa[i]]] = true , rec = sa[i]; 59 } 60 else{ 61 if(!vis[mp[sa[i]]]){ 62 vis[mp[sa[i]]] = true; 63 cnt++; 64 rec = sa[i]; 65 } 66 } 67 } 68 if(flag) ans = tmp; 69 return flag; 70 } 71 int bin_search() 72 { 73 int l=0 , r=1000 , ans=0 , mid; 74 while(l<=r){ 75 mid = (l+r)>>1; 76 if(check(mid)) l=mid+1 , ans=mid; 77 else r=mid-1; 78 } 79 return ans; 80 } 81 int main() 82 { 83 // freopen("a.in" , "r" , stdin); 84 bool flag = false; 85 while(scanf("%d" , &n) , n){ 86 if(flag) puts(""); 87 flag = true; 88 len = 0 , dif = 27; 89 for(int i=0 ; i<n ; i++){ 90 scanf("%s" , s[i]); 91 for(int j=0 ; j<strlen(s[i]) ; j++) all[len] = s[i][j] , mp[len]=i+1 , r[len++] = s[i][j]-‘a‘+1; 92 pos[i][0] = len; 93 all[len] = ‘*‘; 94 mp[len]=i+1 , r[len++] = dif++; 95 } 96 r[len-1] = 0; 97 da(r , sa , len , dif); 98 // for(int i=0 ; i<len ; i++) cout<<"i: "<<i<<" "<<sa[i]<<endl; 99 callHeight(r , sa , len-1); 100 int ret = bin_search(); 101 if(!ret) puts("?"); 102 else{ 103 for(int i=0 ; i<ans.size() ; i++){ 104 for(int j=ans[i] , t=0 ; t<ret ; j++ , t++) printf("%c" , all[j]); 105 puts(""); 106 } 107 } 108 } 109 }
时间: 2024-10-01 02:56:00