bzoj1692(后缀数组)

来源:互联网 发布:淘宝优惠卷名称 编辑:程序博客网 时间:2024/06/03 10:10

对于整个后缀数组的

 

#include<cstdio>#include<cmath>#include<cstdlib>#include<algorithm>#include<cstring>#define maxn 60005using namespace std;int n;//×¢Ò⣬ÒòΪÕâµÀÌâÒª½«×Ö·û´®·´ÏòºóÔÙÁ¬ÉÏ£¬ºó׺Êý×é´óСҪ¿ª´óÒ»±¶ int s[maxn],t1[maxn],t2[maxn],c[maxn],sa[maxn],rank[maxn],height[maxn],f[maxn][20];char a[maxn];void build_sa(){int *x=t1,*y=t2,m=30;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]]]++;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];p=1;swap(x,y);x[sa[0]]=0;for (int i=1;i<n;i++)x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;if (p>=n) break;m=p; }}void build_height()  {      int k=0;     for (int i=0;i<n;i++) rank[sa[i]]=i;      for (int i=0;i<n-1;i++)      {          if (k) k--;          int j=sa[rank[i]-1];          while (s[j+k]==s[i+k]) k++;          height[rank[i]]=k;      }  }  void build_rmq(){for (int i=0;i<n;i++) f[i][0]=height[i];for (int k=1;(1<<k)<=n;k++)for (int i=0;i<n-(1<<k);i++) f[i][k]=min(f[i][k-1],f[i+(1<<(k-1))][k-1]);}int rmp(int l,int r){if (l>r) swap(l,r);l++; int t=(int)(log((double)r-l+1)/log(2.0));return min(f[l][t],f[r-(1<<t)+1][t]);}void debug(){for (int i=0;i<n;i++) printf("%c",s[i]+'A'-1);printf("\n");for (int i=0;i<n;i++) printf("%d ",rank[i]);printf("\n");for (int i=0;i<n;i++) printf("%d ",sa[i]);printf("\n");for (int i=0;i<n;i++) printf("%d ",height[i]);printf("\n");for (int i=0;i<n;i++){for (int j=sa[i];j<n;j++) printf("%c",s[j]+'A'-1);printf("\n");}}int main(){scanf("%d",&n);for (int i=0;i<n;i++){getchar();a[i]=getchar();}int nn=0,tmp=n;for (int i=0;i<n;i++) s[nn++]=a[i]-'A'+1;s[nn++]=27;for (int i=n-1;i>=0;i--) s[nn++]=a[i]-'A'+1;s[nn++]=0;n=nn;build_sa();build_height();build_rmq();//debug();int l=0,r=tmp+1,tot=0;for (int i=0;i<tmp-1;i++){tot++;int lcp=rmp(rank[l],rank[r]);//printf("%d %d %d\n",l,r,lcp);if (s[l+lcp]<s[r+lcp])printf("%c",s[l]+'A'-1),l++;else printf("%c",s[r]+'A'-1),r++;if (tot==80) printf("\n"),tot=0;}printf("%c",s[l]+'A'-1);return 0;}/*6ACDBCB*/


 

总结

1:要尝试做难题,不要沉浸于简单题当中,挑战自己的思维。

2:关于后缀数组的模板一定要搞清楚,不能错

0 0
原创粉丝点击