给出两个长度
n
,
m
n,m
n,m不超过
1
e
5
1e5
1e5的字符串,然后求最长的公共子串的长度。
这个长度的上界是
m
i
n
(
n
,
m
)
min(n,m)
min(n,m),对公共子串的长度二分,预处理两个串的哈希值,然后二分判定的时候对其中一个串所有当前二分长度的哈希值排序,另外一个直接放入其中二分。
复杂度是
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n),不是很优秀,但是好写。
在#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+7;
const int b=133;
char s[N],t[N];
int n,m;
ull hs1[N],hs2[N],p[N];
ull a[N];
bool check(int len) {
int tot=0;
for(int i=1;i+len-1<=n;i++)
a[++tot]=hs1[i+len-1]-hs1[i-1]*p[len];
sort(a+1,a+1+tot);
for(int i=1;i+len-1<=m;i++) {
ull x=hs2[i+len-1]-hs2[i-1]*p[len];
int id=lower_bound(a+1,a+1+tot,x)-a;
if(id!=tot+1&&a[id]==x) return 1;
}
return 0;
}
int main() {
scanf("%s",s+1);
scanf("%s",t+1);
n=strlen(s+1);
m=strlen(t+1);
p[0]=1;
for(int i=1;i<=n;i++)
p[i]=p[i-1]*b;
for(int i=1;i<=n;i++)
hs1[i]=hs1[i-1]*b+s[i];
for(int i=1;i<=m;i++)
hs2[i]=hs2[i-1]*b+t[i];
int l=0,r=min(n,m),ans=0;
while(l<=r) {
int mid=(l+r)>>1;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}