foj 2075 Substring
来源:互联网 发布:淘宝试衣间在线使用 编辑:程序博客网 时间:2024/06/08 07:39
题目链接:http://acm.fzu.edu.cn/problem.php?pid=2075
题目大意:求恰好出现n次的字典序最小的串。
题目思路:后缀数组加单调栈,n为1的时候要特判,不过数据有点水,不判都能过。
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<queue>#include<algorithm>#include<vector>#include<stack>#include<list>#include<iostream>#include<map>using namespace std;#define inf 0x3f3f3f3f#define M 100010int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a<b?a:b;}int height[M],rank[M],r[M],sa[M];int ts[M],ta[M],tb[M],tv[M],pos,st,ed;struct node{ int h,st,w;}q[M];bool cmp(int *y,int a,int b,int l){ return y[a]==y[b]&&y[a+l]==y[b+l];}void da(int n,int m){ int i,j,*x=ta,*y=tb,p; for(i=0;i<m;i++) ts[i]=0; for(i=0;i<n;i++) ts[x[i]=r[i]]++; for(i=1;i<m;i++) ts[i]+=ts[i-1]; for(i=n-1;i>=0;i--) sa[--ts[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { 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++) ts[i]=0; for(i=0;i<n;i++) tv[i]=x[y[i]]; for(i=0;i<n;i++) ts[tv[i]]++; for(i=1;i<m;i++) ts[i]+=ts[i-1]; for(i=n-1;i>=0;i--) sa[--ts[tv[i]]]=y[i]; swap(x,y); x[sa[0]]=0; p=1; for(i=1;i<n;i++) { if(cmp(y,sa[i-1],sa[i],j)) x[sa[i]]=p-1; else x[sa[i]]=p++; } }}void calh(int n){ int i,k,tmp; for(i=1;i<=n;i++) rank[sa[i]]=i; k=0; for(i=0;i<n;i++) { tmp=sa[rank[i]-1]; for(;r[i+k]==r[tmp+k];k++) ; height[rank[i]]=k; k?--k:0; }}char s[M];int solve(int len,int k){ int i; node tmp; int top=0,tail=0; height[len+1]=0; if(k==1) { st=0,ed=len; return 1; } for(i=1;i<=len+1;i++) { tmp.h=0; tmp.st=i; while(top<tail&&q[tail-1].w>=height[i]) { tmp.h+=q[tail-1].h; tmp.st=q[tail-1].st; tmp.w=q[tail-1].w; if(tmp.h==k-1&&tmp.w>height[i]) { st=sa[tmp.st]; if(top<tail-1) ed=st+max(height[i]+1,q[tail-2].w+1); else ed=st+height[i]+1; return 1; } tail--; } if(height[i]==0) continue; tmp.w=height[i]; tmp.h+=1; q[tail++]=tmp; } return 0;}int main(){ int i,k,len; while(scanf("%d",&k)!=EOF) { scanf("%s",s); len=strlen(s); for(i=0;i<len;i++) r[i]=s[i]+1; r[len]=0; da(len+1,200); calh(len); if( solve(len,k)==0) { puts("impossible"); continue; } for(i=st;i<ed;i++) printf("%c",s[i]); puts(""); }}
- foj 2075 Substring
- FOJ 题目 2075 Substring (后缀数组求出现k次的最小字典序子串)
- FOJ月赛被虐
- FOJ 1036
- foj 1689
- FOJ 1615
- foj 1075
- Foj 1382
- foj 1627
- foj 1759
- foj 1607
- foj 1753
- foj 1411
- foj 1402
- foj 2027
- foj 2171
- foj 2139
- foj 2139
- Uva 12436 Rip Van Winkle's Code(区间更新,区间查询)
- MyEclipse的Run as没有了java Application选项
- JDK5 condition线程通信
- Intellij中的常用快捷键
- MyEclipse代码提示快捷键设置
- foj 2075 Substring
- 既是客户又是供应商清帐配置
- 订单成本分析
- Delphi7同时保证多个Activex控件可用的办法
- squid工作原理
- win7指纹登录一直请等待
- C++多核高级编程 - 09 并发模型之 一 Boss-Worker
- HDU OJ 1269 迷宫城堡【有向图强连通分量的Tarjan算法 入门】
- 各软件开发版本详解