题面在此

题解:将字符串分成k部分,然后求最长前缀,所以我们只关注前缀部分就好了,公共前缀后边的是啥不用管,那么问题就转化成了是否存在k个不相交的字符串的最长公共前缀问题。首先用Hash来记录一下字符串,然后再二分枚举最长前缀的长度。怎么样才能保证不相交呢?可以用map记录一段字符串的右边界。然后当这个串再次出现时,判断当前的左边界和上次的右边界时候相交。。这里要用无序map,否则会T,也可以用ull对Hash自动取余。

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e5+;
char s[N];
ll Hash[N],p[N];
ll mod=1e9+;
ll base=;
ll n,m;
unordered_map<ll ,ll >mp1,mp2;
ll getHash(ll x,ll y){
return (Hash[y]%mod-Hash[x-]*p[y-x+]%mod+mod)%mod;
}
bool check(ll x){
mp1.clear();mp2.clear();
for(int i=x;i<=n;i++){
ll tmp=getHash(i-x+,i);
if(mp1[tmp]==) {
mp1[tmp]=i;
mp2[tmp]++;
}
else if(mp1[tmp]<=i-x) {
mp1[tmp]=i;mp2[tmp]++;
}
if(mp2[tmp]>=m) return ;
}
return ;
}
int main(){
cin>>n>>m;
scanf("%s",s+);
p[]=;
for(ll i=;i<=n;i++){
Hash[i]=((Hash[i-]*base)%mod+s[i]-'a')%mod;
p[i]=p[i-]*base%mod;
}
ll ans=;
ll l=,r=n;
while(l<=r){
ll mid=(l+r)/;
if(check(mid)){
ans=max(ans,mid);
l=mid+;
}
else r=mid-;
}
cout<<ans<<endl;
return ;
}

最新文章

  1. $\LaTeX$笔记:首字下沉
  2. Android Studio 2.2的新鲜事
  3. 《oracle每天一练》触发器不能调用或间接调用COMMIT,ROLLBACK等DCL语句
  4. linux read简单用法
  5. 3D Touch集成过程整理
  6. 课堂笔记--Strom并发模型
  7. 创建泛类集合List以及数组转集合,集合转数组的应用
  8. nyoj 93 汉诺塔(三)
  9. Android--数据持久化之内部存储、Sdcard存储
  10. 使用ASP.NET操作IIS7中使用应用程序
  11. 深层次详解Exception
  12. 捕获JSON 解析错误
  13. Maven3.0 服务器配置搭建
  14. Oracle EBS-SQL (PO-4):检查采购订单明细.sql
  15. OWC11生成统计图案例
  16. 一篇文章带你了解Cloud Native
  17. 每日分享!~ JavaScript(拖拽事件)
  18. 判断 Python 版本
  19. 干货分享:让你分分钟学会 javascript 闭包(转)
  20. CSS(三)

热门文章

  1. navicat和pymysql
  2. cmdb简介
  3. 拿 C# 搞函数式编程 - 3
  4. Xamarin.Forms读取并展示Android和iOS通讯录 - TerminalMACS客户端
  5. Java基础语法(7)-数组
  6. nginx使用手册+基本原理+优缺点
  7. iOS 图片的解压缩
  8. MySql查询当天、本周、本月、本季度、本年的数据
  9. Ubuntu添加新用户并给普通用户赋予root新权限
  10. 模块 pillow图像处理