ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Ybtoj #534. 「后缀数组」跳蚤的串

2022-02-06 16:31:27  阅读:175  来源: 互联网

标签:cnt return int Ybtoj mid 534 SA 跳蚤 define


题面传送门
最大值最小显然想到二分。
因为答案肯定是原序列的一个子串,所以直接二分这个子串在本质不同子串中的排名即可。
因为已经预处理了SA,所以在check的时候倒叙,显然一个后缀中字典序最大的串是最长的子串,所以倒叙以后,如果当前点的字典序大于二分的字典序,那么这个位置和上一个位置就必须要分开。这样如果最终段数大于\(k\)则失败,否则成功。
时间复杂度\(O(n\log n)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 100000
#define M N*N+5
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*x+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound  
using namespace std;
int n,m,k,x,y,lg[N+5];char S[N+5];ll l,r,mid,ToT;
namespace SA{
	int H[N+5],sa[N+5],rk[N+5],st[N+5][20];
	struct Ques{int x,y,id;}F[N+5];I bool cmp(Ques x,Ques y){return x.x^y.x?x.x<y.x:x.y<y.y;}
	I void BD(){
		RI i,j;for(i=1;i<=n;i++) F[i]=(Ques){S[i],0,i};sort(F+1,F+n+1,cmp);for(i=1;i<=n;i++) rk[F[i].id]=rk[F[i-1].id]+(F[i].x^F[i-1].x||F[i].y^F[i-1].y);
		for(i=1;i<=n;i<<=1){for(j=1;j<=n;j++) F[j]=(Ques){rk[j],i+j<=n?rk[i+j]:0,j};sort(F+1,F+n+1,cmp);for(j=1;j<=n;j++) rk[F[j].id]=rk[F[j-1].id]+(F[j].x^F[j-1].x||F[j].y^F[j-1].y);if(rk[F[n].id]==n) break;}
		for(i=1;i<=n;i++) sa[rk[i]]=i;for(i=2;i<=n;i++){lg[i]=lg[i/2]+1;H[i]=max(H[rk[sa[i]-1]]-1,0);while(S[sa[i]+H[i]]==S[sa[i-1]+H[i]]) H[i]++;}
		for(i=n;i>1;i--) for(st[i][0]=H[i],j=1;i+(1<<j)-1<=n;j++) st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);for(i=1;i<=n;i++) ToT+=n-sa[i]+1-H[i];
	}
	I int LCP(int x,int y){if(x==y) return n-x+1;x=rk[x];y=rk[y];x>y&&(swap(x,y),0);x++;int d=lg[y-x+1];return min(st[x][d],st[y-(1<<d)+1][d]);}
	I void Find(ll ToT,int &x,int &y){for(RI i=1;i<=n;i++) if(ToT>n-sa[i]+1-H[i]) ToT-=n-sa[i]+1-H[i];else {x=sa[i];y=sa[i]+H[i]+ToT-1;return;}}
}
I int calc(int x,int y,int l,int r){int d=SA::LCP(x,l);if(y-x+1<=d) return r-l+1<=d?(y-x>r-l):0;else return r-l+1<=d?1:(SA::rk[x]^SA::rk[l]?SA::rk[x]>SA::rk[l]:y-x+1>r-l+1);}
I int check(ll mid){SA::Find(mid,x,y);RI i,cnt=0,j,d;for(j=i=n;i;i--){if(calc(i,j,x,y)) cnt++,j=i,i++;if(cnt>k) return 0;}cnt++;return cnt<=k;}
int main(){
	freopen("flea.in","r",stdin);freopen("flea.out","w",stdout);
	RI i;scanf("%d%s",&k,S+1); n=strlen(S+1);SA::BD();l=0;r=ToT;while(l+1<r) mid=l+r>>1,(check(mid)?r:l)=mid;SA::Find(r,x,y);for(i=x;i<=y;i++)Pc(S[i]);
}

标签:cnt,return,int,Ybtoj,mid,534,SA,跳蚤,define
来源: https://www.cnblogs.com/275307894a/p/15865810.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有