不小于k个字符串的最长子串
题目链接:https://cn.vjudge.net/contest/318888#problem/K
题意:
给你n个字符串,求至少出现在向上取整n/2的个串的公共子串如果有多个就输出多个。
思路:
1 #include <stdio.h> 2 #include <iostream> 3 #include <algorithm> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <math.h> 7 #include <queue> 8 #include <set> 9 10 #define INF 0x3f3f3f3f 11 #define pii pair<int,int> 12 #define LL long long 13 using namespace std; 14 typedef unsigned long long ull; 15 const int MAXN = 200005; 16 17 int wa[MAXN], wb[MAXN], wv[MAXN], ws_[MAXN]; 18 void Suffix(int *r, int *sa, int n, int m) 19 { 20 int i, j, k, *x = wa, *y = wb, *t; 21 for(i = 0; i < m; ++i) ws_[i] = 0; 22 for(i = 0; i < n; ++i) ws_[x[i] = r[i]]++; 23 for(i = 1; i < m; ++i) ws_[i] += ws_[i - 1]; 24 for(i = n - 1; i >= 0; --i) sa[--ws_[x[i]]] = i; 25 for(j = 1, k = 1; k < n; j *= 2, m = k) 26 { 27 for(k = 0, i = n - j; i < n; ++i) y[k++] = i; 28 for(i = 0; i < n; ++i) if(sa[i] >= j) y[k++] = sa[i] - j; 29 for(i = 0; i < n; ++i) wv[i] = x[y[i]]; 30 for(i = 0; i < m; ++i) ws_[i] = 0; 31 for(i = 0; i < n; ++i) ws_[wv[i]]++; 32 for(i = 1; i < m; ++i) ws_[i] += ws_[i - 1]; 33 for(i = n - 1; i >= 0; --i) sa[--ws_[wv[i]]] = y[i]; 34 t = x; 35 x = y; 36 y = t; 37 for(x[sa[0]] = 0, i = k = 1; i < n; ++i) 38 x[sa[i]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j]) ? k - 1 : k++; 39 } 40 } 41 int Rank[MAXN], height[MAXN], sa[MAXN], r[MAXN]; 42 void calheight(int *r,int *sa,int n) 43 { 44 int i,j,k=0; 45 for(i=1; i<=n; i++)Rank[sa[i]]=i; 46 for(i=0; i<n; height[Rank[i++]]=k) 47 for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++); 48 } 49 50 char s[MAXN]; 51 int vis[MAXN]; 52 int indexx[MAXN]; 53 int T; 54 vector<int> ans[MAXN]; 55 56 bool check(int x,int n){ 57 for (int i=1;i<n;i++) { 58 if (height[i] < x) 59 continue; 60 int cnt = 0; 61 for (int j = 0; j <= T; j++) { 62 vis[j] = 0; 63 } 64 while (height[i] >= x && i < n) { 65 if (!vis[indexx[sa[i - 1]]]) { 66 vis[indexx[sa[i - 1]]] = 1; 67 cnt++; 68 } 69 i++; 70 } 71 if (!vis[indexx[sa[i - 1]]]) { 72 vis[indexx[sa[i - 1]]] = 1; 73 cnt++; 74 } 75 if (cnt > T / 2) { 76 ans[x].push_back(sa[i - 1]); 77 } 78 } 79 if(ans[x].size()!=0) return true; 80 return false; 81 } 82 83 84 int main() 85 { 86 while (~scanf("%d",&T) && T) { 87 for (int i=0;i<=1000;i++){ 88 ans[i].clear(); 89 } 90 int XX = 30; 91 int n = 0; 92 for (int i=0;i<T;i++){ 93 scanf("%s",s); 94 int len = strlen(s); 95 for (int j=0;j<len;j++){ 96 r[n++] = s[j]-'a'+1; 97 indexx[n-1] = i; 98 } 99 r[n++] = XX++; 100 } 101 r[n] = 0; 102 Suffix(r,sa,n+1,250); 103 calheight(r,sa,n); 104 int L=1,R=1000,mid,len=0; 105 while (L<=R){ 106 mid = (L+R)>>1; 107 if (check(mid,n)){ 108 len = mid; 109 L = mid+1; 110 }else 111 R = mid-1; 112 } 113 if(len==0) printf("?\n"); 114 else 115 { 116 for(int i=0;i<ans[len].size();i++) 117 { 118 for(int j=ans[len][i];j<ans[len][i]+len;j++) 119 printf("%c",(char)r[j]+'a'-1); 120 printf("\n"); 121 } 122 } 123 cout<<endl; 124 } 125 return 0; 126 }