题目链接: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 }