后缀数组板子
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\n");
else printf("%d\n",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\n",l);
}
}