题目链接: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 100010
int 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部分水题AC答案"这个标题表明这是一组来自FOj(可能是某个在线编程竞赛平台的简称)的简单问题,其中部分问题已经得到了正确的解答(AC是Accepted的缩写,表示程序通过了所有测试用例)。 在描述中提到"代Un的...
标题 "FOJ(大部分标程) ACM" 指的是一个与ACM国际大学生程序设计竞赛(ACM International Collegiate Programming Contest, ICPC)相关的资源集合,其中FOJ(可能是"Full Option Judge"的缩写)是用于练习和提交...
给定一个自然数n,由n开始可以依次产生半数集set(n)中的数如下。 (1)n∈set(n); (2)在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半; (3)按此规则进行处理,直到不能再添加自然数为止。...
第一次上传东西... 本人是个初学者,希望大家多多指教
【标题】"foj.rar" 是一个压缩包文件,其主题是"On the Line_meet62l_pick8xd_界面编程"。这个标题暗示了它包含的代码示例可能涉及命令行界面编程,特别是与创建文件相关的快捷方式或实用工具。 【描述】描述指出这...
为了更准确地识别高价值流失客户,研究者通常会关注那些因非财务原因而主动要求停机的客户(FOJ)或欠费后要求停机的客户(FO L)。 ##### 2. 数据理解 数据理解阶段是整个数据挖掘过程中非常关键的一环,它涉及到对...