【贪心】【后缀自动机】Gym - 101466E - Text Editor

题意:给你两个串A,B,以及一个整数K,让你找到B的一个尽可能长的前缀,使得其在A串中出现的次数不小于K次。

对A串建立后缀自动机,然后把B串放在上面跑,由于每到一个结点,该结点endpos集合的大小就是该前缀出现的次数,又由于较长前缀的出现次数不大于较短前缀,所以只要跑到不满足条件停下即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXL 100000
#define MAXC 300
int v[2*MAXL+10],__next[2*MAXL+10],first[2*MAXL+10],e;
void AddEdge(int U,int V){
    v[++e]=V;
    __next[e]=first[U];
    first[U]=e;
}
char s[MAXL+10];
int len;
struct SAM{
    int endcnt[2*MAXL+10];
    int n,maxlen[2*MAXL+10],minlen[2*MAXL+10],trans[2*MAXL+10][MAXC],slink[2*MAXL+10];
    void clear(){
        for(int i=0;i<=n;++i){
            endcnt[i]=maxlen[i]=minlen[i]=slink[i]=first[i]=0;
            memset(trans[i],0,sizeof(trans[i]));
        }
        n=e=0;
    }
    int new_state(int _maxlen,int _minlen,int _trans[],int _slink){
        maxlen[n]=_maxlen;
        minlen[n]=_minlen;
        for(int i=0;i<MAXC;++i){
            if(_trans==NULL){
                trans[n][i]=-1;
            }
            else{
                trans[n][i]=_trans[i];
            }
        }
        slink[n]=_slink;
        return n++;
    }
    int add_char(char ch,int u){
        if(u==-1){
            return new_state(0,0,NULL,-1);
        }
        int c=ch;
        int z=new_state(maxlen[u]+1,-1,NULL,-1);
        endcnt[z]=1;
        int v=u;
        while(v!=-1 && trans[v][c]==-1){
            trans[v][c]=z;
            v=slink[v];
        }
        if(v==-1){
            minlen[z]=1;
            slink[z]=0;
            return z;
        }
        int x=trans[v][c];
        if(maxlen[v]+1==maxlen[x]){
            minlen[z]=maxlen[x]+1;
            slink[z]=x;
            return z;
        }
        int y=new_state(maxlen[v]+1,-1,trans[x],slink[x]);
        slink[y]=slink[x];
        minlen[x]=maxlen[y]+1;
        slink[x]=y;
        minlen[z]=maxlen[y]+1;
        slink[z]=y;
        int w=v;
        while(w!=-1 && trans[w][c]==x){
            trans[w][c]=y;
            w=slink[w];
        }
        minlen[y]=maxlen[slink[y]]+1;
        return z;
    }
    void dfs(int U){
        for(int i=first[U];i;i=__next[i]){
            dfs(v[i]);
            endcnt[U]+=endcnt[v[i]];
        }
    }
    void work_slink_tree(){
        for(int i=1;i<n;++i){
            AddEdge(slink[i],i);
        }
        dfs(0);
    }
}sam;
typedef long long ll;
char s2[MAXL+10];
int len2,K;
int main(){
	gets(s);
    len=strlen(s);
    int U=sam.add_char(0,-1);
    for(int i=0;i<len;++i){
        U=sam.add_char(s[i],U);
    }
    sam.work_slink_tree();
    gets(s2);
    len2=strlen(s2);
    scanf("%d",&K);
    int ans=0;
    U=0;
    for(int i=0;i<len2;++i){
    	if(sam.endcnt[U]<K){
    		ans=i-1;
    		goto OUT;
    	}
    	else if(sam.trans[U][s2[i]]==-1){
    		ans=i;
    		goto OUT;
    	}
    	U=sam.trans[U][s2[i]];
    }
    ans=len2;
    if(sam.endcnt[U]<K){
    	ans=len2-1;
    	goto OUT;
    }
    OUT:
    if(ans==0){
    	puts("IMPOSSIBLE");
    }
    else{
    	for(int i=0;i<ans;++i){
    		putchar(s2[i]);
    	}
    	puts("");
    }
    return 0;
}
posted @ 2018-01-26 08:41  AutSky_JadeK  阅读(336)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト