后缀数组板子

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);
	}
}
原文地址:https://www.cnblogs.com/VIrtu0s0/p/10548655.html