zoukankan      html  css  js  c++  java
  • POJ3693 Maximum repetition substring

    题目

    The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.

    Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.

    大意是,给你一个字符串,让你输出其中重复次数最多的重复连续字串,如果次数相同就输出字典序最小的。

    思路

    一开始不好想。

    首先,枚举串的长度(L),然后枚举区间([1,L])([L+1,2*L]),会发现,一个连续重复子串总会被截头去尾的被枚举到。

    比如cabababc,在枚举到长度(L=2)的时候,中间的那段baba就会被枚举到,然而实际上可能是去了头尾的,注意到LCP求出后后面会多出一段,定义(R=LCP),那么,R%L就是多出来的一段,可以看成是前面少取了L-R%L这一段,然后判断是不是可以把这一段补上,就完成了第一步:找到一段区间内的最长重复连续子串。

    然后考虑第二步:要求字典序最小。

    我们把这些可能成为答案的串先存起来,然后按照的顺序一遍扫描,因为sa天然有序,所以就可以得到最终的答案了。

    代码

    #include<cstdio>
    #include<string.h>
    #include<algorithm> 
    #include<iostream>
    #define M 100005
    using namespace std;
    int sa[M],rk[M],t1[M],t2[M],tmp[M],cnt1[M],cnt2[M],H[M];
    struct node{
    	int x,id;
    	bool operator < (const node&  res)const{
    		if(x!=res.x)return x<res.x;
    		return id<res.id;
    	}
    }A[M];
    void Init(char *s,int n){
    	for(int i=1;i<=n;i++)A[i]=(node){s[i],i};
    	sort(A+1,A+n+1);
    	for(int i=1;i<=n;i++)sa[i]=A[i].id; 
    	rk[sa[1]]=1;
    	for(int i=2;i<=n;i++){
    		rk[sa[i]]=rk[sa[i-1]];
    		if(s[sa[i]]!=s[sa[i-1]])rk[sa[i]]++; 
    	}
    	for(int l=1;rk[sa[n]]<n;l<<=1){
    		for(int i=0;i<=n;i++)cnt1[i]=cnt2[i]=0;
    		for(int i=1;i<=n;i++)cnt1[t1[i]=rk[i]]++,cnt2[t2[i]=(l+i<=n)?rk[i+l]:0]++;
    		for(int i=1;i<=n;i++)cnt1[i]+=cnt1[i-1],cnt2[i]+=cnt2[i-1];
    		for(int i=n;i>=1;i--)tmp[cnt2[t2[i]]--]=i;
    		for(int i=n;i>=1;i--)sa[cnt1[t1[tmp[i]]]--]=tmp[i];
    		rk[sa[1]]=1;
    		for(int i=2;i<=n;i++){
    			rk[sa[i]]=rk[sa[i-1]];
    			if(t1[sa[i]]!=t1[sa[i-1]]||t2[sa[i]]!=t2[sa[i-1]])rk[sa[i]]++;
    		}
    	}
    	for(int i=1,j=0;i<=n;i++){
    		j-=j>0;
    		while(s[i+j]==s[sa[rk[i]-1]+j])j++;
    		H[rk[i]]=j;
    	}
    }
    struct Stable{
    	int mn[M][21],Log[M];
    	void Init(int n){
    		for(int i=1;i<=n;i++){
    			mn[i][0]=H[i];
    			if(i>1)Log[i]=Log[i>>1]+1;
    		}
    		for(int j=1;j<21;j++)
    			for(int i=1;i+(1<<j-1)<=n;i++)
    				mn[i][j]=min(mn[i][j-1],mn[i+(1<<j-1)][j-1]);
    	}
    	int Query(int l,int r){
    		int t=Log[r-l+1];
    		return min(mn[l][t],mn[r-(1<<t)+1][t]);
    	}
    }st;
    int LCP(int l,int r){
    	l=rk[l],r=rk[r];
    	if(l>r)swap(l,r);
    	return st.Query(l+1,r);
    }
    char S[M];
    int n,cas=0,a[M],cnt;
    int main(){
    	while(scanf("%s",S+1)&&S[1]!='#'){
    		n=strlen(S+1);
    		Init(S,n);
    		st.Init(n);
    		int ans=0;
    		for(int L=1;L<=n;L++){
    			for(int i=1;i<=n;i+=L){
    				int R=LCP(i,i+L),step=R/L+1,k=i-(L-R%L);
    				if(k>=0&&R%L)if(LCP(k,k+L)>=R)step++;
    				if(step>ans){ans=step;cnt=0;a[cnt++]=L;}
    				else if(step==ans)a[cnt++]=L;
    			}
    		}
    		int len=-1,st;
    		for(int i=1;i<=n&&len==-1;i++){
    			for(int j=0;j<cnt;j++){
    				int L=a[j];
    				if(LCP(sa[i],sa[i]+L)>=(ans-1)*L){
    					len=L;st=sa[i];break;
    				}
    			}
    		}		
    		printf("Case %d: ",++cas);
    		for(int i=st;i<st+len*ans;i++)printf("%c",S[i]);
    		putchar('
    ');
    		for(int i=1;i<=n;i++)S[i]=0;
    	}
    	return 0;
    }
    
  • 相关阅读:
    Spring自动代理机制
    JUnit4 详解
    struts2 OGNL
    loj4j的配置跟使用
    junit浅学笔记二
    shell变量设置
    zookeeper使用
    [zz]Linux kernel map
    glog 使用中存在的问题
    shell中特殊字符(串)
  • 原文地址:https://www.cnblogs.com/zryabc/p/11202144.html
Copyright © 2011-2022 走看看