zoukankan      html  css  js  c++  java
  • 后缀数组板子

    poj1743
    下标从0开始版本

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<string>
    #define M 20005
    using namespace std;
    int x[M],y[M],sa[M],rk[M],c[M],h[M],s[M];
    int n,i,l,r,mid,m,mx;
    
    void build_sa(){                //m,p要比实际大1
    	for(int i=0;i<m;i++)c[i]=0;
    	for(int i=0;i<n;i++)c[x[i]=s[i]]++;
    	for(int i=1;i<m;i++)c[i]+=c[i-1];
    	for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    	for(int k=1;k<=n;k<<=1){
    		int p=0;
    		for(int i=n-k;i<n;i++)y[p++]=i;
    		for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
    		
    		for(int i=0;i<m;i++)c[i]=0;
    		for(int i=0;i<n;i++)c[x[y[i]]]++;//实际上直接x就行
    		for(int i=1;i<m;i++)c[i]+=c[i-1];
    		for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
    
    		swap(x,y);
    		p=1;x[sa[0]]=0;
    		for(int i=1;i<n;i++)
    			x[sa[i]]=
    				y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
    		if(p>=n)break;
    		m=p;
    	}
    }
    
    void get_heigh(){
    	int k=0;
    	for(int i=1;i<=n;i++)rk[sa[i]]=i;//最后加一位,第n位一定rk=0
    	for(int i=0;i<n;i++){            //不遍历到n,rk就一定不为0
    		if(k)k--;
    		int j=sa[rk[i]-1];
    		while(s[i+k]==s[j+k])k++;
    		h[rk[i]]=k;
    	}
    }
    int ck(int mid){
    	int mi=sa[0],ma=sa[0];
    	for(int i=1;i<n;i++){
    		if(h[i]>=mid){
    			mi=min(sa[i],mi);
    			ma=max(sa[i],ma);
    		}else{
    			mi=sa[i];ma=sa[i];
    		}
    		if(ma-mi>mid)return 1;
    	}
    	return 0;
    }
    int main(){
    	while(~scanf("%d",&n)&&n){
    		mx=0;
    		for(i=0;i<n;i++){
    			scanf("%d",&s[i]);
    		    if(i){s[i-1]=s[i]-s[i-1]+88;mx=max(s[i-1],mx);}
    		}
    		s[n-1]=0;
    		m=mx+1;
    		build_sa();
    		n--;
    		get_heigh();
    		l=0;r=n++;
    		while(l<r){
    			mid=(l+r)/2;
    			if(ck(mid))l=mid+1;
    			else r=mid;
    		}
    		if(!ck(l))l--;
    		if(l+1<5)printf("0
    ");
    		else printf("%d
    ",l+1);
    	}
    }
    

    poj3261
    下标从1开始版本

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<string>
    #define M 1000005
    using namespace std;
    int c[M],x[M],s[M],sa[M],y[M],rk[M],h[M];
    int n,k,i,l,r,mid,m;
    
    void build_sa(){
    	int i;
    	for(i=0;i<=m;i++)c[i]=0;
    	for(i=1;i<=n;i++)c[x[i]=s[i]]++;
    	for(i=1;i<=m;i++)c[i]+=c[i-1];
    	for(i=n;i>=1;i--)sa[c[x[i]]--]=i;
    	
    	for(int k=1;k<=n;k<<=1){
    		int p=0;
    		for(i=n-k+1;i<=n;i++)y[++p]=i;  //有k个不能作为第二关键字
    		for(i=1;i<=n;i++)if(sa[i]>k)y[++p]=sa[i]-k;
    
    		for(i=0;i<=m;i++)c[i]=0;
    		for(i=1;i<=n;i++)c[x[y[i]]]++;
    		for(i=1;i<=m;i++)c[i]+=c[i-1];
    		for(i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i];     //
    
    		swap(x,y);
    		x[sa[1]]=1;p=1;
    	    for(i=2;i<=n;i++){
    			x[sa[i]]=
    				y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p;
    		}
    		if(p>=n)break;
    		m=p;
    	}
    }
    
    void get_heigh(){
    	int k=0;
    	for(int i=1;i<=n;i++)rk[sa[i]]=i;     //sa写成s
    	for(int i=1;i<=n;i++){
    		if(rk[i]==1)continue;
    		if(k)--k;
    		int j=sa[rk[i]-1];
    		while(s[i+k]==s[j+k])k++;        //忘
    		h[rk[i]]=k;
    	}
    }
    
    int ck(int mid){
    	int cnt=1;
    	for(int i=2;i<=n;i++){
    		if(h[i]>=mid){
    			cnt++;
    		}else cnt=1;
    		if(cnt>=k)return 1;
    	}
    	return 0;
    }
    int main(){
    	while(~scanf("%d%d",&n,&k)){
    	    m=0;
    		for(i=1;i<=n;i++){
    		    scanf("%d",&s[i]);
    			m=max(s[i],m);
    		}
    		build_sa();
    		get_heigh();
    		l=1;r=n;
    		while(l<r){
    			mid=(l+r)/2;
    			if(ck(mid))l=mid+1;
    			else r=mid;
    		}
    		if(!ck(l))l--;
    		printf("%d
    ",l);
    	}
    }
    
  • 相关阅读:
    【HDU3721】枚举+最长路
    满足要求的最长上升子序列(nlogn)
    Flask入门 表单Flask-wtf form原生 Bootstrap渲染(七)
    Flask入门之模板导入与块宏(六)
    Flask入门模板过滤器与测试器(五)
    Flask入门模板Jinja2语法与函数(四)
    Flask入门flask-script 蓝本 钩子函数(三)
    Flask入门request session cookie(二)
    Flask入门 flask结构 url_for 重定向(一)
    Django问卷调查项目思路流程
  • 原文地址:https://www.cnblogs.com/VIrtu0s0/p/10548655.html
Copyright © 2011-2022 走看看