首页 > 代码库 > bzoj 4310 跳蚤
bzoj 4310 跳蚤
后缀数组+二分
1.
从后往前贪心扫
当必须分的时候就分一段
注意比较两个串大小时的细节
2.
先二分这个串第一次出现时在后缀数组上的位置
再二分具体是哪个串
从前往后扫,使右端点不断往左缩,当 右<=左 时分一段
快的飞起
1.
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define N 200005#define ll long longusing namespace std;char s[N];int rk[N],sa[N],wb[N],sum[N];void sasa(int n,int m){ int *x=rk,*y=wb; for(int i=0;i<m;i++)sum[i]=0; for(int i=0;i<n;i++)sum[x[i]=s[i]]++; for(int i=1;i<m;i++)sum[i]+=sum[i-1]; for(int i=n-1;i>=0;i--)sa[--sum[x[i]]]=i; for(int j=1,p=1;p<n;m=p,j<<=1) { p=0; for(int i=n-j;i<n;i++)y[p++]=i; for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(int i=0;i<m;i++)sum[i]=0; for(int i=0;i<n;i++)sum[x[i]]++; for(int i=1;i<m;i++)sum[i]+=sum[i-1]; for(int i=n-1;i>0;i--)sa[--sum[x[y[i]]]]=y[i]; swap(x,y);x[sa[0]]=0;p=1; for(int i=1;i<n;i++) x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]?p-1:p++; } return ;}int h[N];void calh(int n){ for(int i=1;i<=n;i++)rk[sa[i]]=i; int k=0; for(int i=0;i<n;i++) { if(k)k--; int j=sa[rk[i]-1]; while(s[j+k]==s[i+k])k++; h[rk[i]]=k; } return ;}int mn[N][20],lg[N],n;void ST(){ lg[0]=-1; for(int i=1;i<=100000;i++)lg[i]=lg[i>>1]+1; for(int i=1;i<=n;i++)mn[i][0]=h[i]; for(int i=1;i<20;i++) { for(int j=1;j<=n;j++) { if(j+(1<<(i-1))<=n) { mn[j][i]=min(mn[j][i-1],mn[j+(1<<(i-1))][i-1]); } else mn[j][i]=mn[j][i-1]; } }return ;}int qur(int l,int r){ int k=lg[r-l+1]; return min(mn[l][k],mn[r-(1<<k)+1][k]);}bool cmp(int x,int len1,int y,int len2){ if(x<y) { int p=qur(x+1,y); if(p>=len2&&p<len1)return 0; return 1; } else if(x>y) { int p=qur(y+1,x); if(p>=len1)return 1; return 0; } else { if(len1<=len2)return 1; return 0; }}int k;bool pan(ll x){ int now=1;ll tot=0; int pos,len; for(int i=1;i<=n;i++) { ll pre=tot; tot+=n-sa[i]-h[i]; if(tot>=x) { pos=i;len=h[i]+x-pre; break; } } int ta=n-1; for(int i=n-1;i>=0;i--) { if(!cmp(rk[i],1,pos,len))return 0; if(!cmp(rk[i],ta-i+1,pos,len)) { ta=i,now++; } } return now<=k;}int main(){ scanf("%d",&k); scanf("%s",s); n=strlen(s); sasa(n+1,256); calh(n); ST(); ll sm=1LL*n*(n+1)/2; for(int i=1;i<=n;i++)sm-=h[i]; ll l=1,r=sm; while(l<r) { ll mid=(l+r)>>1; if(pan(mid))r=mid; else l=mid+1; } ll tot=0; int pos,len; for(int i=1;i<=n;i++) { ll pre=tot; tot+=n-sa[i]-h[i]; if(tot>=l) { pos=i;len=h[i]+l-pre; break; } } for(int i=0;i<len;i++) { putchar(s[sa[pos]+i]); }puts(""); return 0;}
2.
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define N 200005using namespace std;char s[N];int c[N],sa[N],m,n,rk[N],t1[N],t2[N],v[N];void saa(char *s,int n,int m){ int *x=t1,*y=t2; for(int i=0;i<m;i++)c[i]=0; for(int i=0;i<n;i++)c[x[i]=s[i]]++; for(int i=1;i<m;i++)c[i]+=c[i-1]; for(int i=0;i<n;i++)sa[--c[x[i]]]=i; int p=1; for(int j=1;p<n;j<<=1,m=p) { p=0; for(int i=n-j;i<n;i++)y[p++]=i; for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(int j=0;j<m;j++)c[j]=0; for(int i=0;i<n;i++)c[x[i]]++; for(int j=1;j<m;j++)c[j]+=c[j-1]; for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y);x[sa[0]]=0;p=1; for(int i=1;i<n;i++) x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]?p-1:p++; } return ;}int h[N];void calh(int n){ for(int i=1;i<=n;i++)rk[sa[i]]=i; int k=0; for(int i=0;i<n;i++) { if(k)k--; int j=sa[rk[i]-1]; while(s[i+k]==s[j+k])k++; h[rk[i]]=k; } return ;}int main(){ scanf("%d %s",&m,s); n=strlen(s);s[n]=0; saa(s,n+1,300); calh(n); int l=1,r=n; while(l<r) { int mid=(l+r)>>1,num=0,mn=n,m1=n; for(int i=mid+1;i<=n;i++){m1=min(m1,h[i]);v[sa[i]]=m1;if(!h[i])num=m+1;} for(int i=0;i<=n-1;i++) { if(mn==i)num++,mn=n; if(v[i])mn=min(mn,i+v[i]); } if(num+1<=m)r=mid;else l=mid+1; for(int i=mid+1;i<=n;i++)v[sa[i]]=0; } int u=l; l=h[u]+1,r=n-sa[u]; while(l<r) { int mid=(l+r)>>1,k=u,num=0,mn=n,m1=mid; for(int i=u+1;i<=n;i++){m1=min(m1,h[i]);v[sa[i]]=m1;} v[sa[u]]=mid; for(int i=0;i<n;i++) { if(mn==i)num++,mn=n; if(v[i])mn=min(mn,i+v[i]); } if(num+1<=m)r=mid;else l=mid+1; for(int i=k;i<=u;i++)v[sa[i]]=0; } for(int i=1;i<=l;i++)printf("%c",s[sa[u]+i-1]); puts(""); return 0;}
bzoj 4310 跳蚤
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。