后缀数组 模板

来源:互联网 发布:预决算软件 编辑:程序博客网 时间:2024/04/28 23:41
char s[N];//数组的长度要为两倍的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[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];}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]) 的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀

原创粉丝点击