(http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105595#problem/A)
题意:给定n个字符串,求出最长子串,在超过n/2的串中出现过。
做法:后缀数组+尺取
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;
#define ll long long
#define inf 1e18
#define clr(x,y) memset(x,y,sizeof x)
#define FOR(i,a,b) \
for(i=a;a<b?i<=b:i>=b;a<b?i++:i--)
const int maxn = 2e5+20;
char s[maxn];
int sa[maxn],t[maxn],t2[maxn],c[maxn],len;
void build_sa(int m)
{
int n=len;
int i,*x = t,*y = t2;
FOR(i,0,m-1) c[i]=0;
FOR(i,0,n-1) c[x[i]=s[i]]++;
FOR(i,1,m-1) c[i]+=c[i-1];
FOR(i,n-1,0) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1){
int p=0;
FOR(i,n-k,n-1) y[p++]=i;
FOR(i,0,n-1) if(sa[i]>=k) y[p++]=sa[i]-k;
FOR(i,0,m-1) c[i]=0;
FOR(i,0,n-1) c[x[y[i]]]++;
FOR(i,0,m-1) c[i]+=c[i-1];
FOR(i,n-1,0) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;
x[sa[0]]=0;
FOR(i,1,n-1)
x[sa[i]]=y[sa[i-1]]==y[sa[i]] &&
y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
if(p>=n) break;
m=p;
}
}
int Rank[maxn],height[maxn];
int id[maxn];
void getHeight()
{
int k=0,n=len;
for(int i=0;i<n;i++) Rank[sa[i]]=i;
for(int i=0;i<n;i++)
{
if(k) k--;
int j=sa[Rank[i]-1];
while(s[i+k]==s[j+k] && s[i+k]!='$' )
k++;
height[Rank[i]]=k;
}
}
int d[maxn][20] , flog[maxn];
void RMQ_init(int n)
{
for(int i=0;i<n;i++) d[i][0] = height[i];
flog[0]=-1;
for(int i=1;i<n;i++) flog[i]=flog[i>>1]+1;
for(int j=1;(1<<j)<=n;j++)
for(int i=0;i+(1<<j)<=n;i++)
d[i][j] = min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int RMQ(int L,int R)
{
int k = flog[R-L+1];
return min(d[L][k],d[R-(1<<k)+1][k]);
}
char ss[maxn];
int cnt[maxn],sum;
void add(int pos)
{
if( s[sa[pos]] == '$' )
return ;
if( cnt[id[sa[pos]]] == 0 )
sum++;
cnt[id[sa[pos]]]++;
}
void del(int pos)
{
if( s[sa[pos]] == '$' )
return ;
if( cnt[id[sa[pos]]] == 1 )
sum--;
cnt[id[sa[pos]]]--;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
//printf("%d\n",1<<20);
int n;
int fi=1;
while(~scanf("%d",&n))
{
if( n == 0 ) break;
if( fi ) fi=0;
else printf("\n");
if( n == 1 )
{
scanf("%s",ss);
printf("%s\n",ss);
continue;
}
len=0;
for(int i=0;i<n;i++)
{
scanf("%s",ss);
strcat(ss,"$");
int l = strlen(ss);
for(int j=0;j<l;j++)
{
s[len]=ss[j];
id[len]=i;
len++;
}
}
s[len++]=0;
build_sa(255);
getHeight();
RMQ_init(len);
// for(int i=0;i<len;i++)
// printf("%d %s id %d height %d\n",i,s+sa[i],id[sa[i]],height[i]);
clr(cnt,0);
sum=0;
int he=1,st=0;
int longlen = -1;
vector<int>q;
// printf("len %d\n",len);
while( st < len )
{
while( st < len )
{
add(++st);
if( sum*2>n )
break;
}
if( st == len )
break;
while( he < len )
{
del(he++);
if( sum*2<=n )
{
add(--he);
break;
}
}
// printf("he %d st %d\n",he,st);
int la = RMQ(he+1,st);
if( la > longlen )
{
longlen = la;
q.clear();
q.push_back(he);
}
else if( la == longlen )
q.push_back(he);
del(he++);
}
if( q.size() && longlen > 0 )
{
for(int i=0;i<q.size();i++)
{
//printf("%d*\n",q[i]);
if( i && RMQ(q[i-1]+1,q[i]) >= longlen )
continue;
for(int j=0;j<longlen;j++)
printf("%c",s[sa[q[i]]+j]);
printf("\n");
}
}else
printf("?\n");
}
return 0;
}