hdu 3518后缀数组

来源:互联网 发布:青少儿编程 编辑:程序博客网 时间:2024/04/30 09:56

/*

枚举字串的长度1~n/2;

通过height来判断两个字串相同的长度,在符合要求的长度里记录距离最远的两个字串的起始位置l,r

最后通过l+len-1<r来判断重叠,不重叠的加1

 

代码如下:

*/

 

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn = 1100;char s[maxn];int sa[maxn],t[maxn],t2[maxn],c[maxn];void build_sa(int n,int m){int i,k,*x=t,*y=t2,p;//基数排序for(i=0;i<m;i++)  c[i]=0;for(i=0;i<n;i++)  c[x[i]=s[i]]++;for(i=1;i<m;i++)  c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;for(k=1;k<n;k*=2){p=0;//直接利用sa数组排序第二关键字for(i=n-k;i<n;i++)  y[p++]=i;for(i=0;i<n;i++)  if(sa[i]>=k) y[p++]=sa[i]-k;//基数排序第一关键字for(i=0;i<m;i++)  c[i]=0;for(i=0;i<n;i++)  c[x[y[i]]]++;for(i=1;i<m;i++)  c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];//根据sa和y数组计算新的x数组swap(x,y);p=1; x[sa[0]]=0;for(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;}}int rank[maxn],height[maxn];void getHeight(int n){int i,j,k=0;for(i=1;i<=n;i++) rank[sa[i]] = i;for(i=0;i<n;i++){if(rank[i]==1)continue;if(k)k--;j=sa[rank[i]-1];while(s[i+k]==s[j+k])k++;height[rank[i]]=k;}}int main(){    int l,r,i,j,n,ans;    while(scanf("%s",s)&&s[0]!='#'){  ans=0;   n=strlen(s);build_sa(n+1,255);getHeight(n);for(i=1;i<=n/2;i++){l=2000;r=-1;for(j=2;j<=n;j++){if(height[j]>=i){if(sa[j]>r)r=sa[j];if(sa[j-1]>r)r=sa[j-1];if(sa[j]<l)l=sa[j];if(sa[j-1]<l)l=sa[j-1];}else{if(l+i<=r)ans++;l=2000;r=-1;}}if(l+i<=r)ans++;}printf("%d\n",ans);    }    return 0;}


 

原创粉丝点击