#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 2e5+100;
char s[maxn];
int t1[maxn],t2[maxn],c[maxn];
int Rank[maxn],height[maxn],rmq[maxn],mm[maxn];
int best[20][maxn];
char str[maxn];
char str1[maxn];
int r[maxn];
int sa[maxn];
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 rank[], int height[], int n, int m){
n++;
int i, j, p, *x = t1, *y = t2;
for(int i =0;i<m;++i)c[i] = 0;
for(int i =0;i<n;++i)c[x[i]=str[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(j = 1; j<=n; j<<=1){
p = 0;
for(i = n-j; i < n;++i)y[p++] = i;
for(i = 0;i<n;++i)if(sa[i]>=j)y[p++] = sa[i] - j;
for(i = 0;i<m;++i)c[i] = 0;
for(i = 0;i<n;++i)c[x[y[i]]]++;
for(i = 1;i<m;++i)c[i] +=c[i-1];
for(i = n-1;i>=0;i--)sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = 1;
x[sa[0] ] = 0;
for(i = 1;i<n;++i)
x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++;
if(p>=n)break;
m = p;
}
int k =0;
n--;
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(str[i+k] == str[j+k])k++;
height[rank[i]] = k;
}
}
void initrmq(int n){
mm[0] = -1;
for(int i =1;i<=n;++i)
mm[i] = ((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
for(int i =1;i<=n;++i)best[0][i]=i;
for(int i =1;i<=mm[n];i++){
for(int j = 1;j+(1<<i)-1<=n;j++){
int a = best[i-1][j];
int b = best[i-1][j+(1<<(i-1))];
if(rmq[a]<rmq[b])best[i][j] = a;
else
best[i][j] = b;
}
}
}
int askrmq(int a, int b){
int t;
t = mm[b-a+1];
b-=(1<<t)-1;
a = best[t][a];
b = best[t][b];
return rmq[a]<rmq[b]?a:b;
}
int lcp(int a,int b){
a = Rank[a];
b = Rank[b];
if(a>b)swap(a,b);
return height[askrmq(a+1,b)];
}
int t[maxn];
bool cmp1(const int a,const int b){
return height[a]>height[b];
}
int main(){
scanf("%s",str);
scanf("%s",str1);
int len = strlen(str);
int len1 = strlen(str1);
int n = len+len1+1;
for(int i =0;i<len;++i){
r[i] = str[i];
}
for(int i = len+1;i<len+1+len1;++i){
r[i] = str1[i-len-1];
}
r[len] = '#';
r[n] = 0;
int res = 0;
da(r,sa,Rank,height,n,128);
for(int i =1;i<=n;++i){
int rk = i;
if(height[rk]>0){
if((sa[rk]<len&&sa[rk-1]>len)||(sa[rk-1]<len&&sa[rk]>len)){
res = max(res,height[rk]);
// break;
}
}
}
cout<<res<<endl;
}
后缀数组典型题
求两个串最长的相同子串
转换成一个串然后求后缀之中的最长前缀 并且令这两个后缀满足一个在第一个串中 一个在第二个串中
并且合并两个串时中间插入了一个分隔符使得后缀的相同前缀只能是自己串中的子串
后缀数组太优秀了...