当前位置:编程学习 > C/C++ >>

foj 2075 Substring

题目大意:求恰好出现n次的字典序最小的串。

题目思路:后缀数组加单调栈,n为1的时候要特判,不过数据有点水,不判都能过。

[cpp] 
#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(""); 
    } 


补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,