题目大意

给定\(k\)和长度\(\le10^5\)的串S

把串分成不超过\(k\)个子串,然后对于每个子串\(s\),他会从\(s\)的所有子串中选择字典序最大的那一个,并在选出来的\(k\)个子串中再选择字典序最大的那一个。他称其为“魔力串”。

输出最小的魔力串

分析

最大值最小\(\Rightarrow\)二分+判定性问题

考虑对于选出来的\(k\)个子串\(s\),\(s\)中最大子串一定是\(s\)的某个后缀

做法

我们在所有本质不同字符串中按找字典序进行二分

得到一段字符

因为\(s\)中最大子串一定是\(s\)的某个后缀

我们从后往前扫(从前往后就\(n^2\)了),不行就分多一段

记录last表示上一次分割的地方

那么扫到\(i\)时\(i-last\)就是当前\(s\)的后缀

比较一下即可\(~~\) cmp调了一个小时还好意思说即可

bool cmp(int x,int y,int l1,int l2){//s[x..x+l1-1],s[y..y+l2-1]
int tp=lcp(x,y);
if(tp<l1&&tp<l2) return s[x+tp]>s[y+tp];//在比较范围直接比较
return l1>l2; //否则直接比较长度
}

实现用后缀数组方便许多

后缀树麻烦一点

solution

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int M=200007; int n,m,st,len;
char s[M];
int id[M];
int last,tot;
int ch[M][26];
int fa[M],stp[M];
int ed[M];
int dfn[M],pid[M],tdfn;
int pre[M][20],dep[M],Mx;
LL sum[M]; struct edge{int y,nxt;};
struct vec{
int g[M],te;
edge e[M];
vec(){memset(g,0,sizeof(g)); te=0;}
void clear(){memset(g,0,sizeof(g)); te=0;}
inline void push(int x,int y){e[++te].y=y;e[te].nxt=g[x];g[x]=te;}
inline int& operator () (int &x) {return g[x];}
inline edge& operator [] (int &x) {return e[x];}
}go,chr; int newnode(int ss){
stp[++tot]=ss;
return tot;
} int ext(int p,int q,int d){
int nq=newnode(stp[p]+1); ed[nq]=ed[q]-(stp[q]-(stp[p]+1));
fa[nq]=fa[q]; fa[q]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
for(;p&&ch[p][d]==q;p=fa[p]) ch[p][d]=nq;
return nq;
} int sam(int p,int d){
int np=ch[p][d];
if(np) return (stp[p]+1==stp[np]) ? np : ext(p,np,d); np=newnode(stp[p]+1); ed[np]=n;
for(;p&&!ch[p][d];p=fa[p]) ch[p][d]=np;
if(!p) fa[np]=1;
else{
int q=ch[p][d];
fa[np]= (stp[p]+1==stp[q]) ? q : ext(p,q,d);
}
return np;
} void dfs(int x){
dfn[x]=++tdfn;
pid[tdfn]=x;
sum[tdfn]=stp[x]-stp[fa[x]];
int p,y;
for(p=go(x);p;p=go[p].nxt){
y=go[p].y;
dep[y]=dep[x]+1;
pre[y][0]=x;
dfs(y);
}
} int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int t=Mx;t>=0;t--)
if(dep[pre[x][t]]>=dep[y]) x=pre[x][t];
if(x==y) return x;
for(int t=Mx;t>=0;t--)
if(pre[x][t]!=pre[y][t]) x=pre[x][t],y=pre[y][t];
return pre[x][0];
} int find(LL num){
int l=1,r=tdfn,mid;
while(l<r){
mid=l+r>>1;
if(sum[mid]>=num) r=mid;
else l=mid+1;
}
return l;
} void getkth(LL num){
int ps=find(num);
int p=pid[ps];
num=sum[ps]-num;
st=ed[p]-stp[p]+1;
len=stp[p]-num;
} int lcp(int x,int y){
return stp[LCA(id[x],id[y])];
} bool cmp(int x,int y,int l1,int l2){
int tp=lcp(x,y);
if(tp<l1&&tp<l2) return s[x+tp]>s[y+tp];
return l1>l2;
} bool check(){
int i,lst=n,blk=0;
for(i=n;i>0;i--){
if(s[i]>s[st]) return 0;
if(cmp(i,st,lst-i+1,len)) blk++,lst=i;
}
return blk+1<=m;
} int main(){ int i,j,p; scanf("%d",&m);
scanf("%s",s+1);
n=strlen(s+1); last=tot=1;
for(i=n;i>0;i--) id[i]=last=sam(last,s[i]-'a'); for(i=2;i<=tot;i++)
chr.push(s[ed[i]-(stp[i]-stp[fa[i]])+1]-'a',i); for(i=26;i>=0;i--)
for(p=chr(i);p;p=chr[p].nxt)
go.push(fa[chr[p].y],chr[p].y); dfs(1);
Mx=log2(tot);
for(j=1;j<=Mx;j++)
for(i=1;i<=tot;i++) pre[i][j]=pre[pre[i][j-1]][j-1];
for(i=1;i<=tdfn;i++) sum[i]+=sum[i-1]; LL l=1,r=sum[tdfn],mid;
while(l<r){
mid=l+(r-l)/2;
getkth(mid);
if(check()) r=mid;
else l=mid+1;
}
getkth(l);
for(i=st;i<=st+len-1;i++) printf("%c",s[i]); puts("");
return 0;
}

最新文章

  1. Android开发学习之路-记一次CSDN公开课
  2. Myeclipse的show in breadcrumb
  3. sql rollup解决责任人收支余额
  4. wikioi 1201 最小数和最大数
  5. 在phalcon框架下,php接口规范以及接口实例
  6. C 各种数据类型介绍
  7. NOIP2015普及组第四题推销员
  8. Oracle获取表字段名,字段类型,字段长度,注释
  9. MariaDB报错Plugin &#39;InnoDB&#39; init function returned error.解决方案
  10. cafee编译错误几个总结
  11. Spring MVC配置实例
  12. 微信小程序之mpvue+iview踩坑之旅
  13. js 日期格式化函数(可自定义)
  14. [UE4]不精准射击 Random Unit Vector in Cone in Radians
  15. python Django Nginx+ uWSGI 安装配置
  16. 【数组】Find Minimum in Rotated Sorted Array
  17. C#各种异常处理方式
  18. KM算法(最优匹配)
  19. P4234 最小差值生成树
  20. PAT 天梯赛 L2-007. 家庭房产 【并查集】

热门文章

  1. css与html结合四种方式
  2. 第31题:LeetCode946. Validate Stack Sequences验证栈的序列
  3. SpingBoot之多Profile文件
  4. [mysql] Can&#39;t read from messagefile
  5. Linux菜鸟起飞之路【一】基本知识与Linux的安装
  6. 获取页面URL参数值
  7. 排序算法合集(Java)
  8. 科学计算库Numpy——数组形状
  9. Python 枚举类源码解析
  10. Roads in the North POJ - 2631