hdu5030 Rabbit's String 后缀数组
2015-09-18 11:22
232 查看
把一个字符串最多分为k段,所有每一段的最大子串的最大值最小。
二分答案串是排名多少的字串,根据sum可以定位该串的位置,在t之后的后缀中有些串是需要切割的,这些串加上后一个字符会大于答案串,把这些串的位置求出后贪心最少切多少刀。
二分答案串是排名多少的字串,根据sum可以定位该串的位置,在t之后的后缀中有些串是需要切割的,这些串加上后一个字符会大于答案串,把这些串的位置求出后贪心最少切多少刀。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<vector> #include<set> #include<map> #include<queue> #include<bitset> #define fi first #define se second #define pii pair<int,int> #define ll long long #define inf 1<<30 #define eps 1e-8 using namespace std; const int maxn=100005; int n,k; char str[maxn]; int s[maxn]; ll sum[maxn]; int cc[maxn]; int t1[maxn],t2[maxn],c[maxn]; int sa[maxn],ra[maxn],height[maxn]; void buildSa(int s[],int n,int m)//最大值小于m { int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=s[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1) { p=0; for(i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; if(p>=n)break; m=p; } } void getHeight(int s[],int n) { int i,j,k=0; for(i=0;i<=n;i++)ra[sa[i]]=i; for(i=0;i<n;i++) { if(k)k--; j=sa[ra[i]-1]; while(s[i+k]==s[j+k])k++; height[ra[i]]=k; } } bool ok(ll mid) { int t=lower_bound(sum,sum+n+1,mid)-sum; int l=sa[t],r=n-sum[t]+mid-1; int len=r-l+1; for(int i=0;i<=n;i++) cc[i]=-1; if(l+len-1<n-1) cc[l]=len; int ans=0; for(int i=t+1;i<=n;i++) { len=min(len,height[i]); if(len==0) return false; if(sa[i]+len-1<n-1) cc[sa[i]]=len; } int m=n; for(int i=0;i<n;i++) { if(i==m) { ans++; if(ans>=k) return false; m=n; } if(cc[i]!=-1) { m=min(m,i+cc[i]); } } return ans+1<=k; } void solve() { sum[0]=0; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+n-sa[i]-height[i]; ll l=1,r=sum ; while(l<r) { ll mid=(l+r)/2; if(ok(mid)) r=mid; else l=mid+1; } int t=lower_bound(sum,sum+n+1,l)-sum; int le=sa[t]; int rr=n-sum[t]+l-1; for(int i=le;i<=rr;i++) putchar(str[i]); puts(""); } int main() { while(~scanf("%d",&k) && k) { scanf("%s",str); n=strlen(str); for(int i=0;i<=n;i++) s[i]=str[i]; buildSa(s,n+1,128); getHeight(s,n); solve(); } return 0; }
相关文章推荐
- Activity生命周期保存参数onSaveInstanceState()与onRestoreInstanceState()
- Nginx日志参数
- JQuery自定义动画animate方法
- Java中成员变量和局部变量的区别
- 【Flex布局】
- 生成二维码图片
- TextRank简介
- <一>Copy和mutableCopy——iOS开发的疑惑
- 深度链接(Deep-linking)是移动和网络之间缺失的链接
- iOS 9 Bitcode新问题集成第三方解决方案
- NameNode---Exception in namenode join
- 海格面试题总结
- matlab中文件的复制
- java.lang.NumberFormatException 错误及解决办法
- Django中错误:django.core.exceptions.ImproperlyConfigured: ***DEFAULT_INDEX_TABLESPACE解决方
- RS-485设计指南 (TI:SLLA272B-2008.05)
- java Map key value 取值的方法
- IOS动态类型isKindOfClass, isMemberOfClass
- Android基础入门教程——7.6.4 基于UDP协议的Socket通信
- Android 踩坑记录