思路:找出现次数大于n/2次的最大子串,一个子串出现多次,那么他们的排名肯定是相邻的,所以利用height数组,找出相邻排名最长公共前缀长度等于 K 的区间。看看这个区间中的个数是否大于n/2, 满足的话这个k长度就符合。所有我们需要枚举k的大小,可以用二分查找这个临界点。
#include
using namespace std;
typedef long long ll;
const int INF=1<<30;
const int N=1e5+1000;
int t1[N], t2[N], c[N], MAX;
bool cmp(int *r, int a, int b, int l){
return r[a]==r[b] && r[a+l]==r[b+l];
}
void da(int str[], int sa[], int rk[], int height[], int n, int m){
n++;
int i, j, p, *x=t1, *y=t2;
for(i=0; i=0; i--) sa[--c[x[i]]]=i;
for(j=1; j<=n; j<<=1){
p=0;
for(i=n-j; i=j) y[p++]=sa[i]-j;
for(i=0; i=0; i--) sa[--c[x[y[i]]]]=y[i];
swap(x, y);
p=1; x[sa[0]]=0;
for(i=1; i=n) break;
m=p;
}
int k=0;
n--;
for(i=0; i<=n; i++) rk[sa[i]]=i;
for(i=0; i st;
st.insert(id[sa[0]]);
for(int i=0; i<=cnt; i++){
while(i=len){
st.insert(id[sa[i]]);
i++;
}
if(st.size()>n/2){
if(f)
return true;
for(int j=sa[i-1]; j>1;
if(judge(mid, 1)){
l=mid+1;
}
else
r=mid-1;
}
judge(r, 0);
}
void init(){
MAX=0; cnt=0;
}
int main(){
int f=0;
while(~scanf("%d", &n) && n){
init();
if(f) puts("");
if(!f) f=1;
for(int i=1; i<=n; i++){
scanf("%s", str);
MAX=max(MAX, (int)strlen(str));
for(int j=0; str[j]; j++){
id[cnt]=i;
s[cnt++]=str[j]-'a'+1;
}
id[cnt]=i;
s[cnt++]=26+i;
}
s[cnt]=0;
if(n==1){
puts(str);
continue;
}
da(s, sa, rk, height, cnt, 26+n+1);
solve();
}
return 0;
}