You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial traits such as height, colour, wrinkles, ears, eyebrows and the like. A few bear no human resemblance; these typically have geometric or amorphous shapes like cubes, oil slicks or clouds of dust.
The answer is given in the 146th episode of Star Trek - The Next Generation, titled The Chase. It turns out that in the vast majority of the quadrant’s life forms ended up with a large fragment of common DNA.
Given the DNA sequences of several life forms represented as strings of letters, you are to find the longest substring that is shared by more than half of them.
Input
Standard input contains several test cases. Each test case begins with 1 ≤ n ≤ 100, the number of life forms. n lines follow; each contains a string of lower case letters representing the DNA sequence of a life form. Each DNA sequence contains at least one and not more than 1000 letters. A line containing 0 follows the last test case.
Output
For each test case, output the longest string or strings shared by more than half of the life forms. If there are many, output all of them in alphabetical order. If there is no solution with at least one letter, output “?”. Leave an empty line between test cases.
Sample Input
3
abcdefg
bcdefgh
cdefghi
3
xxx
yyy
zzz
0
Sample Output
bcdefg
cdefgh
?
这题和POJ3080有点像,一起讲一下这题和POJ3080有点像,一起讲一下这题和POJ3080有点像,一起讲一下
POJ3080POJ3080POJ3080是在nnn个字符串中,求字典序最小的最长公共子串,那么直接二分长度,然后与heightheightheight数组比较。
如果heightheightheight满足条件,那么还要判断sa[i—1]sa[i—1]sa[i—1]以及sa[i]sa[i]sa[i]是否在两个不同的字符串中,因为同个字符串的最长公共前缀是没有意义的,最后判断是否有n个连续的后缀满足。
本题是要在n个字符串中,求所有的最长公共子串,这些串必须满足在一半以上的字符串中出现过。步骤和上面一样,只是最后判断条件变成判断一半。
(PS:还是UVA的数据牛逼啊。。。。debug半天发现是板子错了!!)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x) x&-x;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 1e6+5;
int s1[maxn];char s2[maxn];
int sa[maxn];
int c[maxn];
int x[maxn],y[maxn],rk[maxn],h[maxn],id[maxn],vis[1005];
int n,m,K,ca;
string ans;
void get_SA(){
mem(c,0);
for(int i = 0; i <= n; i++) ++c[x[i] = s1[i]];
for(int i = 1; i <= m; i++) c[i] += c[i-1];
for(int i = n; i >= 0; i--) sa[--c[x[i]]] = i;
for(int k = 1; k <= n; k <<= 1){
int p = 0;
for(int i = n-k+1; i <= n; i++) y[p++] = i;
for(int i = 0; i <= n; i++)
if(sa[i] >= k) y[p++] = sa[i]-k;
for(int i = 0; i <= m; i++) c[i] = 0;
for(int i = 0; i <= n; i++) c[x[y[i]]]++;
for(int i = 1; i <= m; i++) c[i] += c[i-1];
for(int i = n; i >= 0; i--){
sa[--c[x[y[i]]]] = y[i];
}
swap(x,y);
x[sa[0]] = 0;
p = 1;
for(int i = 1; i <= n; i++){
x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k])?p-1:p++;
}
if(p >= n+1) break;
m = p;
}
}
void get_Height(){
int k = 0;
for(int i = 0; i <= n; i++) rk[sa[i]] = i;
for(int i = 0; i < n; i++){
if(k) k--;
int j = sa[rk[i]-1];
while(s1[i+k] == s1[j+k]) k++;
h[rk[i]] = k;
}
}
bool check(int xx){
int cnt = 0;
mem(vis,0);
for(int i = 2; i <= n; i++){
if(h[i] >= xx){
if(!vis[id[sa[i]]]) vis[id[sa[i]]] = 1,cnt++;
if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]] = 1,cnt++;
if(cnt*2 > ca){
return true;
}
}else{
mem(vis,0);
cnt = 0;
}
}
return false;
}
void judge(int xx){
int cnt = 0;
mem(vis,0);
for(int i = 2; i <= n; i++){
if(h[i] >= xx){
if(!vis[id[sa[i]]]) vis[id[sa[i]]] = 1,cnt++;
if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]] = 1,cnt++;
if(cnt*2 > ca){
ans = "";
for(int j = 0; j < xx; j++){
ans += s1[sa[i]+j]+'a'-1;
}
cnt = 0;
cout<<ans<<endl;
}
}else{
mem(vis,0);
cnt = 0;
}
}
}
void print(int mid){
judge(mid);
}
int main(){
while(~scanf("%d",&ca) && ca){
n = 0,m = 255;
int len,mx = 0;
for(int i = 1; i <= ca; i++){
scanf("%s",s2);
len = strlen(s2);
mx = max(mx,len);
for(int j = 0; j < len; j++){
id[n] = i;
s1[n++] = s2[j]-'a'+1;
}
s1[n++] = 26+i; //无效字符分割,并且注意要用不同的无效字符,避免无效字符产生公共前缀
}
s1[n] = 0;
if(ca == 1){
puts(s2);
puts("");
continue;
}
get_SA();
get_Height();
int l = 0, r = mx,ok = -1;
while(l <= r){
int mid = (l+r)>>1;
if(check(mid)){
ok = mid;
l = mid+1;
}else r = mid-1;
}
if(ok <= 0) puts("?");
else{
print(ok);
}
cout<<endl;
}
}