SPOJ 694 后缀数组

来源:互联网 发布:淘宝大马士革刀真假 编辑:程序博客网 时间:2024/06/07 18:40

简略题意:求不相同的子串的个数。

求出sa之后,会发现每按名次加入一个后缀,会产生n-sa[i]个新的子串,其中有height[i]个之前已经出现过。答案为n-sa[i]+height[i]。

#include <iostream>#include <cstring>#include <map>#include <cstdio>#include <vector>#include <algorithm>using namespace std;struct SuffixArray{    static const int maxn = 1e6+7;    int s[maxn], n, m;    int sa[maxn], rank[maxn], height[maxn];    int t[maxn], t2[maxn], c[maxn];    int MIN[maxn][30];    void build_sa(){        s[n++] = 0;        int *x = t, *y = t2;        for(int i=0; i<m; i++) c[i] = 0;        for(int i=0; i<n; i++) c[x[i]=s[i]]++;        for(int i=1; i<m; i++) c[i]+=c[i-1];        for(int i=n-1; i>=0; i--) sa[--c[x[i]]] = i;        for(int k=1; k<=n; k<<=1){            int p = 0;            for(int i=n-k; i<n; i++) y[p++] = i;            for(int i=0; i<n; i++) if(sa[i]>=k) y[p++] = sa[i]-k;            for(int i=0; i<m; i++) c[i] = 0;            for(int i=0; i<n; i++) c[x[y[i]]]++;            for(int i=1; i<m; i++) c[i]+=c[i-1];            for(int i=n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i];            swap(x, y);            p = 1; x[sa[0]] = 0;            for(int i=1; i<n; i++)                x[sa[i]] = y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;            if(p >= n) break;            m=p;        }        n--;    }    void getheight(){        int k = 0;        for(int i=1; i<=n; i++) rank[sa[i]] = i;        for(int i=0; i<n; i++){            if(k) k --;            int j = sa[rank[i]-1];            while(s[i+k] == s[j+k]) k++;            height[rank[i]] = k;        }    }    void RMQ_init(){        for(int i=0; i<n; i++) MIN[i][0] = height[i+1];        for(int j=1; (1<<j)<=n; j++){            for(int i=0; i+(1<<j)<=n; i++){                MIN[i][j] = min(MIN[i][j-1], MIN[i+(1<<(j-1))][j-1]);            }        }    }    int RMQ(int L, int R){        int k = 0;        while((1<<(k+1)) <= R-L+1) k++;        return min(MIN[L][k], MIN[R-(1<<k)+1][k]);    }    int LCP(int i, int j){         if(rank[i] > rank[j]) swap(i, j);        return RMQ(rank[i], rank[j]-1);    }    void init(char *str, int _n){        m = 130;        n = _n;        memset(height, 0, sizeof height);        for(int i=0; i<n; i++)            s[i] = (int)str[i];        build_sa();        getheight();        RMQ_init();    }    int check(int x, int k) {        int cnt = 1;        for(int i = 2; i <= n; i++) {            if(height[i] >= x) {                cnt ++;                if(cnt >= k) return 1;            } else {                cnt = 1;            }        }        return cnt >= k;    }    void solve() {        int cnt = 0;        for(int i = 1; i <= n; i++)            cnt += n - sa[i] - height[i];        printf("%d\n", cnt);    }}suffix;int t;char str[1100];int main() {    scanf("%d", &t);    while(t--) {        scanf("%s", str);        suffix.init(str, strlen(str));        suffix.solve();    }    return 0;}
原创粉丝点击