spoj 694 Distinct Substrings (后缀数组)

来源:互联网 发布:px4源码下载 编辑:程序博客网 时间:2024/06/11 01:46

算法合集之《后缀数组——处理字符串的有力工具》里面的例题,思路也在里面,不过里面说“ 对于每一次新加进来的后缀 suffix(sa[k]),它将产生 n-sa[k]+1 个新的前缀”,我在代码中 写的是“n-sa[k]”,因为sa数组计数的时候是从0开始的,所以,直接减掉就是增加的新的前缀的个数。

#include <cstdio>#include <cstring>const int MAXN = 1010;int r[MAXN],K,N,sa[MAXN];int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];int cmp(int *r,int a,int b,int l){    return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int *r,int *sa,int n,int m){    int i,j,p,*x=wa,*y=wb,*t;    for(i=0; i<m; i++) ws[i]=0;    for(i=0; i<n; i++) ws[x[i]=r[i]]++;    for(i=1; i<m; i++) ws[i]+=ws[i-1];    for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;    for(j=1,p=1; p<n; j*=2,m=p)    {        for(p=0,i=n-j; i<n; i++) y[p++]=i;        for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;        for(i=0; i<n; i++) wv[i]=x[y[i]];        for(i=0; i<m; i++) ws[i]=0;        for(i=0; i<n; i++) ws[wv[i]]++;        for(i=1; i<m; i++) ws[i]+=ws[i-1];        for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;    }    return;}int rank[MAXN],height[MAXN];void calheight(int *r,int *sa,int n){    int i,j,k=0;    for(i=1; i<=n; i++) rank[sa[i]]=i;    for(i=0; i<n; height[rank[i++]]=k)        for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);    return;}char str[MAXN];int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%s",str);        int len = strlen(str);        for(int i = 0; i < len; ++i)            r[i] = str[i];        r[len] = 0;        da(r,sa,len+1,130);        calheight(r,sa,len);        int res = 0;        for(int i = 1; i <= len; ++i)            res += (len-sa[i]-height[i]);        printf("%d\n",res);    }    return 0;}
0 0