• cogs 2605 寒假ing


    题目链接
    题解:
    其实这道题是poj3693的弱化版,不用考虑字符串的字典序。
    博客链接
    还是先枚举循环节长度T,再枚举i,保证iT,(i+1)T下标合法。对于这两个下标求a=LCP(iT,(i+1)T)。因为不用考虑字符串是谁,只需要知道循环节个数最大值即可,因此是有更简单的做法的,即不需要求iT,(i+1)T的LCS。
    简单地说,如果(T|a),此时iT前面即使还能匹配上也不可能再多一个循环节,否则这个子串就是由(i-1)T,iT访问的了。所以直接用(lfloorfrac{a}{T} floor+1)更新答案即可。如果不整除,那么可能在前面多匹配些,会多一个循环节,那就再求一下(b=LCP(iT-l+amod l,(i+1)T-l+amod l)),用(lfloorfrac{b}{T} floor+1)更新一下答案,复杂度(O(nln n))

    code

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    #define fcl fclose(stdin); fclose(stdout); return 0
    int n;
    char str[100010];
    int C[100010],Ws[100010],Rank[100010],Sa[100010],Height[100010],ST[50010][19];
    int Table[50010];
    void Da(){
    	int i,j,c,k,m=200,p;
    	memset(Ws,0,(m+1)<<2);
    	for(i=0;i<n;++i) Ws[Rank[i]=str[i]]++;
    	for(i=1;i<=m;++i) Ws[i]+=Ws[i-1];
    	for(i=0;i<n;++i) Sa[--Ws[Rank[i]]]=i;
    	for(c=1;c<=n;c<<=1,m=p){
    		for(j=0,i=n-c;i<n;++i) C[j++]=i;
    		for(i=0;i<n;++i) if(Sa[i]>=c) C[j++]=Sa[i]-c;
    		memset(Ws,0,(m+1)<<2);
    		for(i=0;i<n;++i) Ws[Rank[i]]++;
    		for(i=1;i<=m;++i) Ws[i]+=Ws[i-1];
    		for(i=n-1;i>=0;--i) Sa[--Ws[Rank[C[i]]]]=C[i];
    		for(C[Sa[0]]=0,i=1,p=0;i<n;++i)
    			C[Sa[i]]=(Rank[Sa[i]]==Rank[Sa[i-1]]&&Rank[Sa[i]+c]==Rank[Sa[i-1]+c]?p:++p);
    		memcpy(Rank,C,n<<2);
    	}
    	for(i=0,j=0,k=0;i<n;++i){
    		if(Rank[i]==0) continue;
    		for(k=(k?k-1:0),j=Sa[Rank[i]-1];str[i+k]==str[j+k];++k);
    		Height[Rank[i]]=k;
    	}
    	for(i=n-1;i>=0;--i){
    		ST[i][0]=Height[i];
    		for(j=0;j<17;++j){
    			if(i+(1<<j)<n) ST[i][j+1]=min(ST[i][j],ST[i+(1<<j)][j]);
    			else ST[i][j+1]=ST[i][j];
    		}
    	}
    }
    inline int Lcp(int a,int b){
    	a=Rank[a]; b=Rank[b];
    	if(a>b) swap(a,b);
    	a++;
    	return min(ST[a][Table[b-a+1]],ST[b-(1<<Table[b-a+1])+1][Table[b-a+1]]);
    }
    int main(){
    	freopen("broken.in","r",stdin);
    	freopen("broken.out","w",stdout);
    	
    	int T;
    	for(int i=1,k=0;i<=50000;i<<=1,++k){
    		for(int j=i;j<(i<<1)&&j<=50000;++j) Table[j]=k;
    	}
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d",&n);
    		scanf("%s",str);
    		str[n++]='$'; str[n]=0;
    		Da();
    		int l,i,x,y,ans=1;
    		for(l=1;(l<<1)<=n;++l){
    			for(i=0;i+l<n;i+=l*(y/l+1)){
    				x=i+l;
    				y=Lcp(i,x);
    				ans=max(ans,y/l+1);
    				if(y%l) ans=max(ans,1+Lcp(i-l+y%l,x-l+y%l)/l);
    			}
    		}
    		printf("%d
    ",ans);
    	}
    	fcl;
    }
    
  • 相关阅读:
    【转】有关Managed code和Native code的区别
    【转】wince6.0 vs2005 编译选项详解
    【转】Wince Device Emulator使用介绍Device Emulator 2.0
    Dapper基础增删查改、事务和存储过程
    SharpCompress的压缩文件解压和文件夹压缩
    MVC WebAPI 的基本使用
    prepare for travel 旅行准备
    gossip
    JS笔记(3) 词汇结构(待续。。。)
    Good Points Bad Points
  • 原文地址:https://www.cnblogs.com/kito/p/7111437.html
Copyright © 2020-2023  润新知