Nowcoder Practice 61 E.相似的子串(Hash&二分)
题意:求给定字符串中相同但不相交的子串最大个数。
思路:二分查找子串长度,然后对每个长度从右端开始递推结果。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,mod=1e9+7;
typedef unsigned long long ull;
ull h[N],p[N]={1};
char s[N];
int n,k,ans;
bool fun(int len){
map<ull,pair<int,int> >mp;
for(int i=len;i<=n;i++){
ull v=h[i]-h[i-len]*p[len];
if(i-mp[v].first>=len) mp[v].first=i,mp[v].second++;//如果右端还有子串则更新右端和个数.
if(mp[v].second>=k) return 1;
}
return 0;
}
int main(){
scanf("%d%d",&n,&k);
scanf("%s",s+1);
for(int i=1;i<=n;i++)//预处理
p[i]=p[i-1]*233,h[i]=h[i-1]*233+s[i];
int l=1,r=n/k;
while(l<=r){//二分查找最大值。
int mid=(l+r)>>1;
if(fun(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}