`
yiheng
  • 浏览: 156661 次
社区版块
存档分类

foj 2075 Substring

阅读更多

题目链接: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答案"这个标题表明这是一组来自FOj(可能是某个在线编程竞赛平台的简称)的简单问题,其中部分问题已经得到了正确的解答(AC是Accepted的缩写,表示程序通过了所有测试用例)。 在描述中提到"代Un的...

    FOJ(大部分标程) ACM

    标题 "FOJ(大部分标程) ACM" 指的是一个与ACM国际大学生程序设计竞赛(ACM International Collegiate Programming Contest, ICPC)相关的资源集合,其中FOJ(可能是"Full Option Judge"的缩写)是用于练习和提交...

    FOJ.1207.zip_26.2_了然foj

    给定一个自然数n,由n开始可以依次产生半数集set(n)中的数如下。 (1)n∈set(n); (2)在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半; (3)按此规则进行处理,直到不能再添加自然数为止。...

    FOJ 1150 Peter's smokes

    第一次上传东西... 本人是个初学者,希望大家多多指教

    foj.rar_On the Line_meet62l_pick8xd_界面编程

    【标题】"foj.rar" 是一个压缩包文件,其主题是"On the Line_meet62l_pick8xd_界面编程"。这个标题暗示了它包含的代码示例可能涉及命令行界面编程,特别是与创建文件相关的快捷方式或实用工具。 【描述】描述指出这...

    数据挖掘在电信客户流失中的应用

    为了更准确地识别高价值流失客户,研究者通常会关注那些因非财务原因而主动要求停机的客户(FOJ)或欠费后要求停机的客户(FO L)。 ##### 2. 数据理解 数据理解阶段是整个数据挖掘过程中非常关键的一环,它涉及到对...

Global site tag (gtag.js) - Google Analytics