用后缀数组求最长前缀
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <math.h>
#define MAXN 200010
using namespace std;
int m1[MAXN],m2[MAXN];
char s[2*MAXN];
int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],n;
void Build_Sa(int n){//m是基数排序字符的长度
int m;
int i,*x=t,*y=t2;
m=(n<256?256:n);
//基数排序
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[i]=s[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1){
int p=0;
//直接利用sa数组排序第二关键字
for(i=n-k;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
//基数排序第一关键字
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=0;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
//根据sa和y数组计算新的x数组
swap(x,y);
p=1;x[sa[0]]=0;
for(i=1;i<n;i++)
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;//以后即使继续倍增,sa也不会改变,退出下次基数排序的最大值
m=p;//这个m是一直在变的,所以m只需要给出第一次基数排序的长度就可以了
}
}
int rank[MAXN],height[MAXN];
void getHeight(int n){
int i,j,k=0;
for(i=0;i<n;i++) rank[sa[i]]=i;
for(i=0;i<n;i++){
if(k) k--;
j=sa[rank[i]-1];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
int main(){
int m,n,i,j,k,l1,l2;
char str2[MAXN];
while(scanf("%s%s",s,str2)!=EOF){
//构造"str#str1"
l1=strlen(s);
l2=strlen(str2);
strcat(s,"*");
strcat(s,str2);
n=strlen(s);
puts(s);
Build_Sa(n);
getHeight(n);
int p,q,ans;
for(i=1,ans=0;i<n;i++){
/*
if(sa[i]-l2>=0) p=1;
else p=-1;
if(sa[i-1]-l2<0) q=1;
else q=-1;
弄清楚sa数组里面的含义
http://www.nocow.cn/index.php/%E5%90%8E%E7%BC%80%E6%95%B0%E7%BB%84
*/
if((__int64)(sa[i]-l1)*(sa[i-1]-l1)<0 && ans<height[i]) ans=height[i];
}
printf("%d\n",ans);
}
}