hdu 3518 后缀数组

来源:互联网 发布:全国中小学数据库 编辑:程序博客网 时间:2024/05/30 23:23

晚饭前写的代码,一直wa,一直想不通,后来写程序对拍了,一百组数据中错了一组,然后还是想不通为什么的,然后的然后看了别人的代码,然后瞬间知道自己为什么wa!还是对后缀数组了解的不够,自己默认的是sa中排在前面的然后在字符串数组中下标也是在前面的,然后就没有挨个比较相同长度中的取最大值和最小值,所以wa的可怜啊,不过在比赛前又找到自己的一个缺陷好高兴啊,说明以后做这类题ac率又提高了,哈哈!

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#include<stack>#include<vector>#include<climits>#include<map>using namespace std;#define rep(i,n) for(int i=0; i<n; i++)#define repf(i,n,m) for(int i=(n); i<=(m); ++i)#define repd(i,n,m) for(int i=(n); i>=(m); --i) #define ll long long#define arc(a) ((a)*(a))#define inf 100000#define exp 0.000001#define N 3005char s[N];int n;int sa[N*2],high[N*2],rank[N*2],tmp[N*2],top[N*2];void makesa(){memset(sa,0,sizeof(sa));memset(high,0,sizeof(high));memset(rank,0,sizeof(rank));memset(tmp,0,sizeof(tmp));memset(top,0,sizeof(top));n=strlen(s);n++;s[n]='$';int na,len;na=(n<256?256:n);memset(top,0,sizeof(top));rep(i,n) top[rank[i]=s[i] & 0xff]++;repf(i,1,na-1) top[i]+=top[i-1];rep(i,n) sa[--top[rank[i]]]=i;for(len=1; len<n; len<<=1){int j;rep(i,n){j=sa[i]-len;if(j<0) j+=n;tmp[top[rank[j]]++]=j;}sa[tmp[top[0]=0]]=j=0;repf(i,1,n-1){if(rank[tmp[i]]!=rank[tmp[i-1]] || rank[tmp[i]+len]!=rank[tmp[i-1]+len])top[++j]=i;sa[tmp[i]]=j;}rep(j,n+1) rank[j]=sa[j];rep(j,n+1) sa[j]=tmp[j];if(j>=n-1) break;}}void lcp(){int i,j,k;high[0]=0;j=rank[0];for(i=0,k=0; i<n-1; i++,k++) while(k>=0 && s[i]!=s[sa[j-1]+k]) high[j]=(k--),j=rank[sa[j]+1];}void solve(){int ans=0;int l,r;repf(i,1,n/2){l=1200,r=-1;repf(j,1,n-1){if(high[j]>=i){r=max(r,sa[j]);r=max(r,sa[j-1]);l=min(l,min(sa[j],sa[j-1]));}else{if(r-l>=i) ans++;l=1200,r=-1;}}if(l!=1200 && r!=-1) if(r-l>=i) ans++;}cout<<ans<<endl;}int main(){    while(scanf("%s",s))   {   int len=strlen(s);   if(len==1 && s[0]=='#') break;   makesa();   lcp();   solve();   }   return 0;}