您的位置:首页 > 其它

后缀数组 模板

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]) 的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: