zoukankan      html  css  js  c++  java
  • 【贪心】【后缀自动机】Gym

    题意:给你两个串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;
    }
  • 相关阅读:
    近来感受
    GIT相关命令
    CMMI评审总结
    Windows下Git Bash的设置
    PHP学习三--常用运算符和结构语句
    PHP学习二--常量
    MYSQL基础十一--存储引擎
    MYSQL基础十--存储过程
    MYSQL基础九--自定义函数
    MYSQL基础八--子查询和连接
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/8357990.html
Copyright © 2011-2022 走看看