Problem I: 失恋的小T(后缀数组)

来源:互联网 发布:java画图 编辑:程序博客网 时间:2024/05/22 18:24

一道题补了3天最后还是补出来了。学习了后缀数组的倍增法构造(真是美丽)。

思路:这道题目很基础的后缀数组求不相同子串的个数,首先倍增构造,然后求出LCP数组。

对于每个后缀而言对于总串的个数的贡献在不考虑重复的情况下是(n-sa【i】),但是还需要减去重复的,这样每个后缀的贡献就变成了(n-sa【i】-height【i】),扫描一遍求和即可。


全是板子。。。。

 #include<iostream>    #include<cstdio>    #include<cstring>    #include<queue>    #include<cmath>    #include<string>    #include<vector>    #include<algorithm>    #include<map>    #include<set>    #define maxn 50005    #define eps 1e-8    #define zero(a) fabs(a)<eps    using namespace std;    //以下为倍增算法求后缀数组    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(const char *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 sa[maxn],Rank[maxn],height[maxn];    //求height数组    void calheight(const char *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 slove(int n){        int sum=0;        for(int i=1;i<=n;i++)            sum+=n-sa[i]-height[i];        return sum;    }    int main(){        int t;         while( scanf("%s",str)!=EOF){             da(str,sa,strlen(str)+1,130);            calheight(str,sa,strlen(str));            for(int i=1;i<=strlen(str);i++){}//                 printf("%d %d\n",sa[i],height[i]);            printf("%d\n",slove(strlen(str)));        }        return 0;    }


1 0
原创粉丝点击