hdu5030 Rabbit's String 后缀数组
来源:互联网 发布:软件集成商 编辑:程序博客网 时间:2024/05/17 01:03
把一个字符串最多分为k段,所有每一段的最大子串的最大值最小。
二分答案串是排名多少的字串,根据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-8using 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[n]; 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;}
0 0
- hdu5030 Rabbit's String 后缀数组
- 【后缀数组】 HDOJ 5030 Rabbit's String
- HDU 5030 Rabbit's String 后缀数组
- hdu 5030 Rabbit's String(后缀数组)
- HDU 5030 Rabbit's String 后缀数组 二分 构造
- Hdu 5030 Rabbit's String (后缀数组)
- hdu 5030 Rabbit's String(后缀数组&二分)
- POJ 3729 Facer’s string (后缀数组)
- POJ 3729 Facer’s string(后缀数组)
- POJ 3729 Facer's string (后缀数组)
- POJ 3729 Facer’s string (后缀数组 两串后缀的LCP为K的对数)
- HDU 6194 string string string [后缀数组]
- HDU 6194 string string string【后缀数组】
- hdu6194 string string string 后缀数组 + RMQ
- hdu 5030 Rabbit's String sa+rmq+二分
- Ural 1590. Bacon’s Cipher 后缀数组
- hdu5558 Alice's Classified Message (后缀数组)
- string string string hdu 6194 (后缀数组做法)
- SecondaryNameNode--Failed to start secondary namenode
- leetcode | Reverse Linked List
- 关于C#中深拷贝和浅拷贝的认识
- Nagios配置——添加Linux主机监控
- No resource identifier found for attribute 'cardBackgroundColor' in package异常解决
- hdu5030 Rabbit's String 后缀数组
- (2.1.2.6)ThreadPoolExecutor的应用和实现分析(上)—— 应用
- 销售提成计算
- Linux下的串口编程
- 【数据结构】循环链表
- gcc-linaro-arm-linux-gbueabihf 编译后执行后报错 “no such file orr directory”
- frame动画的实现(MessageQueue.IdleHandler)
- MetaException(message:Got exception: org.apache.hadoop.ipc.RemoteException Cannot create directory /
- 销售下单表