hdu 3518-后缀数组(无重叠子串)

来源:互联网 发布:科比生涯数据场均得分 编辑:程序博客网 时间:2024/06/08 07:17

链接:点击打开链接


题解:利用后缀数组先排序,然后求出连续>=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;  }


阅读全文
0 0