zoukankan      html  css  js  c++  java
  • POJ3693 Maximum repetition substring (后缀数组)

    POJ-3693 Maximum repetition substring (后缀数组)

    题意:求连续重复次数最多的子串

    一个连续重复子串可以描述为\(l,r,len\)(端点,循环节长度)

    \(O(n^2)\):直接枚举\(l,len\),然后求\(l\)\(l+len\)\(LCP\),就能得到最大的\(r\)

    考虑不一一枚举\(l\)

    枚举\(len\)之后,从一个点开始向前取\(LCP\),向后取\(LCP\),就能够拼出一个完整的循环串

    用这种方法可以去掉大量重复枚举,只枚举\(l=k\cdot len (k\in Z)\)

    用ST表查询可以做到\(O(n \ln n)\)

    细节似乎蛮多的,代码很烦

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cctype>
    #include<cstring>
    #include<cassert>
    using namespace std;
    
    namespace Folder{
    #define reg register
    #define pb push_back
    	typedef long long ll;
    	typedef unsigned long long ull;
    #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
    	template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    	template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
    	char IO;
    	//template <class T=int> 
    	int rd(){
    		int s=0;
    		int f=0;
    		while(!isdigit(IO=getchar())) f|=(IO=='-');
    		do s=(s<<1)+(s<<3)+(IO^'0');
    		while(isdigit(IO=getchar()));
    		return f?-s:s;
    	}
    }
    using namespace Folder;
    
    
    const int N=1e5+10,INF=1e9;
    int n;
    char s[N];
    int kase;
    #define ms(a) memset(a,0,sizeof a)
    struct Sparse_Table{
    	int s[20][N],Log[N];
    	void PreMake(const int *a){ 
    		rep(i,2,n) Log[i]=Log[i>>1]+1;
    		rep(i,1,n) s[0][i]=a[i];
    		rep(i,1,Log[n]) {
    			int len=(1<<(i-1));
    			rep(j,1,n-(1<<i)+1) s[i][j]=min(s[i-1][j],s[i-1][j+len]);
    		}
    	}
    	int Que(int l,int r) {
    		int d=Log[r-l+1];
    		return min(s[d][l],s[d][r-(1<<d)+1]);
    	}
    };
    
    struct Suffix_Array{
    	int cnt[N],rk[N<<1],sa[N],tmp[N],lcp[N];
    	Sparse_Table ST;
    	void PreMake(char *s){
    		n=strlen(s+1);
    		memset(cnt,0,800);
    		rep(i,1,n) cnt[(int)s[i]]++;
    		rep(i,1,200) cnt[i]+=cnt[i-1];
    		rep(i,1,n) rk[i]=cnt[(int)s[i]],sa[i]=i;
    		rep(i,n+1,n*2) rk[i]=0;
    		for(reg int k=1;k<=n;k<<=1) {
    			rep(i,0,n) cnt[i]=0;
    			rep(i,1,n) cnt[rk[i+k]]++;
    			rep(i,1,n) cnt[i]+=cnt[i-1];
    			drep(i,n,1) tmp[cnt[rk[i+k]]--]=i;
    
    			rep(i,0,n) cnt[i]=0;
    			rep(i,1,n) cnt[rk[i]]++;
    			rep(i,1,n) cnt[i]+=cnt[i-1];
    			drep(i,n,1) sa[cnt[rk[tmp[i]]]--]=tmp[i];
    
    			rep(i,1,n) tmp[sa[i]]=tmp[sa[i-1]]+(rk[sa[i]]!=rk[sa[i-1]]||rk[sa[i]+k]!=rk[sa[i-1]+k]);
    			rep(i,1,n) rk[i]=tmp[i];
    		}
    		int h=0;
    		memset(lcp,0,(n+2)*4);
    		rep(i,1,n) {
    			int j=sa[rk[i]-1];
    			if(h) h--;
    			while(i+h<=n && j+h<=n && s[i+h]==s[j+h]) h++;
    			lcp[rk[i]-1]=h;
    		}
    		ST.PreMake(lcp);
    	}
    	int Que(int x,int y){
    		if(x==y) return n-x+1;
    		if(rk[x]>rk[y]) swap(x,y);
    		return ST.Que(rk[x],rk[y]-1);
    	}
    }SA,RSA;
    Sparse_Table ST;
    
    
    int main(){
    	while(~scanf("%s",s+1) && s[1]!='#') {
    		n=strlen(s+1);
    		SA.PreMake(s),reverse(s+1,s+n+1),RSA.PreMake(s);
    		ST.PreMake(SA.rk);
    		int ans=0,st,ed;
    		rep(i,1,n) {
    			rep(j,1,n) {
    				int a=i*(j-1)+1,b=i*j+1;
    				if(b>n) break;
    				int len=SA.Que(a,b)+RSA.Que(n-a+1,n-b+1)-1; // 向前和向后找LCP
    				if(len<0) continue;
    				if(len<i) continue;
    				int l=a-RSA.Que(n-a+1,n-b+1)+1,r=b+SA.Que(a,b)-1;
    				int p=SA.sa[ST.Que(l,r-(len/i+1)*i+1)];
    				l=p,r=p+(len/i+1)*i-1;
    				if(len/i+1>ans) ans=len/i+1,st=l,ed=r;
    				else if(len/i+1==ans && (SA.rk[st]>SA.rk[l]||(SA.rk[st]==SA.rk[l]&& r-l+1<ed-st+1) ) ) st=l,ed=r;
    			}
    		}
    		if(!ans) ans=1,st=SA.sa[1],ed=SA.sa[1];
    		reverse(s+1,s+n+1);
    		printf("Case %d: ",++kase);
    		rep(i,st,ed) putchar(s[i]);
    		putchar('\n');
    	}
    }
    
    
  • 相关阅读:
    安居客scrapy房产信息爬取到数据可视化(下)-可视化代码
    安居客scrapy房产信息爬取到数据可视化(上)-scrapy爬虫
    反贪风暴4-猫眼影评从爬取到可视化
    vue实战:路由监听
    vue实战——登录页面
    一个电商首页
    网页换肤
    小游戏—九宫格(拼图游戏)
    复选框(checkbox)、多选框
    CSS实现水平垂直居中
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12213819.html
Copyright © 2011-2022 走看看