后缀数组 模板
2013-08-26 17:04
357 查看
char s ;//数组的长度要为两倍的 int n;//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 ='$'; 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]; } int main() { gets(s); int len=strlen(s); s[len]='$'; gets(s+len+1); makesa(); lcp(); int ans=0; repf(i,1,n-1)//到n-1就行了,因为n是在len的长度上加2,n也行,其实自己就很迷糊的 // if((len-sa[i])*(len-sa[i-1])<0) if((sa[i]<len && sa[i-1]>len) || (sa[i]>len && sa[i-1]<len)) if(ans<high[i]) ans=high[i]; cout<<ans<<endl; return 0; }
sa[i]代表的是排第i的字符的位置.rank[i]代表的是第i个排第几的
high数组:定义high[i]=suffix(sa[i-1]) suffix(sa[i]) 的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀