zoukankan      html  css  js  c++  java
  • [TJOI2015]弦论

    我们先求出该字符串的(SA)(Ht)

    然后分类讨论

    (T=0)时,每次去掉(Ht)往后扫就行

    (T=1)时,我们考虑(lcp)对答案的影响

    既然用到(lcp),那就要用(ST)表维护

    左端点固定时,随右端点的增大,区间(min)单调不升

    我们就可以用二分+限制右端点的方式统计某个后缀的前缀的贡献

    循环遍历每个后缀时,由于(Ht)部分已经统计过对答案的贡献,就不用再计算了,从(Ht+1)的位置继续向后统计即可

    #include"cstdio"
    #include"cstring"
    #include"iostream"
    #include"algorithm"
    using namespace std;
    
    const int MAXN=5e5+5;
    
    int ln,maxn,p,t;
    int SA[MAXN],id[MAXN],rnk[MAXN],bnk[MAXN],Ht[MAXN];
    char ch[MAXN];
    int ST[19][MAXN],lg[MAXN];
    
    void shel()
    {
    	for(int i=1;i<=ln;++i) ++bnk[rnk[id[i]]];
    	for(int i=1;i<=maxn;++i) bnk[i]+=bnk[i-1];
    	for(int i=1;i<=ln;++i) SA[++bnk[rnk[id[i]]-1]]=id[i];
    	for(int i=0;i<=maxn;++i) bnk[i]=0;
    	return;
    }
    
    void GetSA()
    {
    	for(int i=1;i<=ln;++i) rnk[i]=ch[i],id[i]=i,maxn=max(maxn,rnk[i]);
    	shel();
    	for(int k=1;k<ln;k<<=1){
    		for(int i=1;i<=k;++i) id[i]=ln-k+i;
    		int ct=k;
    		for(int i=1;i<=ln;++i) if(SA[i]>k) id[++ct]=SA[i]-k;
    		shel();swap(id,rnk);rnk[SA[1]]=1;
    		for(int i=2;i<=ln;++i) rnk[SA[i]]=(id[SA[i]]==id[SA[i-1]]&&id[SA[i]+k]==id[SA[i-1]+k])?rnk[SA[i-1]]:rnk[SA[i-1]]+1;
    		if(rnk[SA[ln]]==ln) return;
    		maxn=rnk[SA[ln]];
    	}return;
    }
    
    void GetHt()
    {
    	int k=0;
    	for(int i=1;i<=ln;++i){
    		if(rnk[i]==1) continue;
    		if(k) --k;
    		int ct=SA[rnk[i]-1];
    		while(ct+k<=ln&&i+k<=ln&&ch[i+k]==ch[ct+k]) ++k;
    		Ht[rnk[i]]=k;
    	}return;
    }
    
    int Getmi(int l,int r){int tmp=lg[r-l+1];return min(ST[tmp][l+(1<<tmp)-1],ST[tmp][r]);}
    
    void slv1()
    {
    	for(int i=1;i<=ln;++i) lg[i]=i>>lg[i-1]+1?lg[i-1]+1:lg[i-1];
    	for(int i=1;i<=ln;++i) ST[0][i]=Ht[i];
    	for(int j=1;j<=lg[ln];++j){
    		int tmp=1<<j-1;
    		for(int i=tmp<<1;i<=ln;++i){
    			ST[j][i]=min(ST[j-1][i],ST[j-1][i-tmp]);
    		}
    	}for(int i=1;i<=ln;++i){
    		int tmp=SA[i]+Ht[i];
    		int ct=ln;
    		while(1){
    			if(tmp>ln) break;
    			if(ct==i){
    				if(t>ln-tmp+1){t-=ln-tmp+1;break;}
    				for(int j=SA[i];j<=tmp+t-1;++j) putchar(ch[j]);
    				return;
    			}int l=i,r=ct;
    			while(l<r){
    				int mid=l+r+1>>1;
    				if(Getmi(i+1,mid)>=tmp-SA[i]+1) l=mid;
    				else r=mid-1;
    			}ct=r;
    			if(t>r-i+1) t-=r-i+1;
    			else{
    				for(int j=SA[i];j<=tmp;++j) putchar(ch[j]);
    				return;
    			}++tmp;
    		}
    	}puts("-1");
    	return;
    }
    
    void slv2()
    {
    	int ct=1;
    	while(t>ln-SA[ct]-Ht[ct]+1) t-=ln-SA[ct]-Ht[ct]+1,++ct;
    	if(ct>ln){puts("-1");return;}
    	for(int i=SA[ct];i<=SA[ct]+t+Ht[ct]-1;++i) putchar(ch[i]);
    	puts("");
    	return;
    }
    
    int main()
    {
    	scanf("%s",ch+1);ln=strlen(ch+1);
    	GetSA();GetHt();scanf("%d%d",&p,&t);
    	p?slv1():slv2();
    	return 0;
    }
    
  • 相关阅读:
    Blank page instead of the SharePoint Central Administration site
    BizTalk 2010 BAM Configure
    Use ODBA with Visio 2007
    Handling SOAP Exceptions in BizTalk Orchestrations
    BizTalk与WebMethods之间的EDI交换
    Append messages in BizTalk
    FTP protocol commands
    Using Dynamic Maps in BizTalk(From CodeProject)
    Synchronous To Asynchronous Flows Without An Orchestration的简单实现
    WSE3 and "Action for ultimate recipient is required but not present in the message."
  • 原文地址:https://www.cnblogs.com/AH2002/p/10223659.html
Copyright © 2011-2022 走看看