zoukankan      html  css  js  c++  java
  • 【BZOJ4310】—跳蚤(后缀数组+二分答案)

    传送门

    darkbzojdarkbzoj上题面有误,应该是最大的最小

    考虑二分这个最小的串xx的排名kk
    那么也就是说所有排名比这个大的一定要被切开

    考虑一个后缀S[p,n]S[p,n]
    如果lcp(S[p,n],x)=0lcp(S[p,n],x)=0那么显然不合法
    否则考虑在lcplcp前切开

    考虑从后往前考虑每个后缀
    那么显然每次在p+1p+1切开一定就是最优的

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define pic pair<int,char>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    #define poly vector<int>
    #define chemx(a,b) ((a)<(b)?(a)=(b):0)
    #define chemn(a,b) ((a)>(b)?(a)=(b):0)
    cs int N=100005;
    namespace Sa{
    	int n,m,rk[N],sa[N],cnt[N],sa2[N],ht[N],s[N];
    	inline void buc_sort(){
    		for(int i=1;i<=m;i++)cnt[i]=0;
    		for(int i=1;i<=n;i++)cnt[rk[sa2[i]]]++;
    		for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    		for(int i=n;i>=1;i--)sa[cnt[rk[sa2[i]]]--]=sa2[i];
    	}
    	inline void buildsa(char *a){
    		n=strlen(a+1),m=30;
    		for(int i=1;i<=n;i++)s[i]=a[i]-'a'+1;
    		for(int i=1;i<=n;i++)rk[i]=s[i],sa2[i]=i;
    		buc_sort();
    		for(int pos=0,i=1;i<=n&&pos<n;i<<=1){
    			pos=0;
    			for(int j=n-i+1;j<=n;j++)sa2[++pos]=j;
    			for(int j=1;j<=n;j++)if(sa[j]>i)sa2[++pos]=sa[j]-i;
    			buc_sort();
    			swap(rk,sa2);
    			rk[sa[1]]=1,pos=1;
    			for(int j=2;j<=n;j++)
    			rk[sa[j]]=(sa2[sa[j-1]]==sa2[sa[j]]&&sa2[sa[j-1]+i]==sa2[sa[j]+i])?pos:++pos;
    			m=pos;
    		}
    		for(int i=1,j,k=0;i<=n;ht[rk[i++]]=k)
    		for(k?k--:0,j=sa[rk[i]-1];s[j+k]==s[i+k];k++);
    	}
    	int lg[N],st[20][N<<1];
    	inline void buildst(){
    		for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
    		for(int i=2;i<=n;i++)st[0][i]=ht[i];
    		for(int i=1;(1<<i)<=n;i++)
    		for(int j=1;j+(1<<i)-1<=n;j++)
    		st[i][j]=min(st[i-1][j],st[i-1][j+(1<<(i-1))]);
    	}
    	inline int Lcp(int x,int y){
    		if(x==y)return n-x+1;
    		x=rk[x],y=rk[y];
    		if(x>y)swap(x,y);x++;
    		int t=lg[y-x+1];
    		return min(st[t][x],st[t][y-(1<<t)+1]);
    	}
    	inline ll calc(){
    		ll res=0;
    		for(int i=1;i<=n;i++)res+=n-sa[i]+1-ht[i];
    		return res;
    	}
    	inline pii getkth(ll k){
    		ll res=0;
    		for(int i=1;i<=n;i++){
    			if(res<k&&res+n-sa[i]+1-ht[i]>=k){
    				pii now;
    				now.fi=sa[i];
    				now.se=k-res+sa[i]+ht[i]-1;
    				return now;
    			}
    			res+=n-sa[i]+1-ht[i];
    		}
    	}
    	inline bool comp(int l1,int r1,int l2,int r2){
    		int len=min(r1-l1+1,r2-l2+1);
    		int lcp=Lcp(l1,l2);
    		if(lcp<len)return s[l1+lcp]<s[l2+lcp];
    		return r1-l1+1<r2-l2+1;
    	}
    	inline bool check(ll k,int tim){
    		pii now=getkth(k);int last=n+1;
    		for(int i=n;i;i--){
    			if(comp(i,n,now.fi,now.se))continue;
    			int lcp=min(now.se-now.fi+1,Lcp(now.fi,i));
    			if(lcp==0)return false;
    			if(i+lcp<last)tim--,last=i+1;
    		}
    		if(last>1)tim--;
    		if(tim<0)return false;
    		return true;
    	}
    	inline void solve(int k){
    		ll l=1,r=calc(),res=r;
    		while(l<=r){
    			ll mid=(l+r)>>1;
    			if(check(mid,k))r=mid-1,res=mid;
    			else l=mid+1;
    		}
    		pii now=getkth(res);
    		for(int i=now.fi;i<=now.se;i++)putchar(s[i]+'a'-1);
    	}
    }
    int n,k;
    char s[N];
    int main(){
    	k=read();
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	Sa::buildsa(s);
    	Sa::buildst();
    	Sa::solve(k);
    }
    
  • 相关阅读:
    Java初学—类与对象
    linux dd命令测试U盘读写速度
    路由器的几种访问方式
    制作Linux启动盘并安装Linux系统到实体机
    RAID阵列与LVM逻辑卷组创建
    有关Linux下库的概念、生成和升级和使用等
    LInux中VIM的使用和定制
    如何通过mount命令挂载存储设备
    硬盘分区和系统启动
    RAID阵列与LVM逻辑卷组原理
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328443.html
Copyright © 2011-2022 走看看