链接:点击打开链接
题解:利用后缀数组先排序,然后求出连续>=k的hight,然后判断最大差距有没有超过就行了。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e3+10;
char s[N];
int wx[N],wy[N],sa[N],ws[N],ran[N],hight[N];
void jsort(int m){
int n=strlen(s)+1,p;
int *x=wx,*y=wy;//以下先对1长度进行基数排序
for(int i=0;i<m;i++) ws[i]=0;
for(int i=0;i<n;i++) ws[x[i]=s[i]]++;
for(int i=1;i<m;i++) ws[i]+=ws[i-1];
for(int i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
for(int k=1;p<n;k<<=1,m=p){
p=0;
for(int i=n-k;i<n;i++) y[p++]=i;
for(int i=0;i<n;i++) if(sa[i]-k>=0) y[p++]=sa[i]-k;
for(int i=0;i<m;i++) ws[i]=0;
for(int i=0;i<n;i++) ws[x[y[i]]]++;
for(int i=1;i<m;i++) ws[i]+=ws[i-1];
for(int i=n-1;i>=0;i--) sa[--ws[x[y[i]]]]=y[i];
swap(x,y),p=1,x[sa[0]]=0;//排名0的位置肯定是0,这里以防溢出
for(int i=1;i<n;i++)
if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]) x[sa[i]]=p-1;
else x[sa[i]]=p++;
}
}
void Gethight(){
int len=strlen(s);
for(int i=1;i<=len;i++) ran[sa[i]]=i;
for(int i=0,k=0;i<len;i++){
if(k) k--;
int j=sa[ran[i]-1];
while(s[i+k]==s[j+k]) k++;
hight[ran[i]]=k;
}
}
int main(){
while(~scanf("%s",s)&&s[0]!='#'){
int len=strlen(s),cnt=0;
for(int i=0;i<len;i++) s[i]=s[i]-'a'+1;
jsort(200);
Gethight();
s[len]=0;
for(int i=1;i<=len/2;i++){
int MIN=sa[1],MAX=sa[1];
for(int j=2;j<=len;j++){//查找连续的hight大于k的位置
if(hight[j]>=i){
MAX=max(MAX,sa[j]);
MIN=min(MIN,sa[j]);
}else{
if(MAX-MIN>=i) cnt++;
MAX=MIN=sa[j];
}
}
if(MAX-MIN>=i) cnt++;
}
printf("%d\n",cnt);
}
return 0;
}