字符串

来源:互联网 发布:倒带和彩虹歌词知乎 编辑:程序博客网 时间:2024/06/07 20:15

后缀数组

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#define ll long longusing namespace std;const int _ = 100004;namespace SA{    int dat[_],sa[_], rk[_], hei[_];    int wa[_], wb[_], wv[_], wd[_];    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 n, int m){          //  倍增算法 r为待匹配数组  n为总长度 m为字符范围        int i, j, p, *x = wa, *y = wb, *t;        for(i = 0; i < m; i ++) wd[i] = 0;        for(i = 0; i < n; i ++) wd[x[i]=r[i]] ++;        for(i = 1; i < m; i ++) wd[i] += wd[i-1];        for(i = n-1; i >= 0; i --) sa[-- wd[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 ++) wd[i] = 0;            for(i = 0; i < n; i ++) wd[wv[i]] ++;            for(i = 1; i < m; i ++) wd[i] += wd[i-1];            for(i = n-1; i >= 0; i --) sa[-- wd[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 ++;            }        }    }    void calHei(int *r, int n)    {        int i, j, k = 0;        for(i = 1; i <= n; i ++) rk[sa[i]] = i;        for(i = 0; i < n; hei[rk[i ++]] = k){            for(k ? k -- : 0, j = sa[rk[i]-1]; r[i+k] == r[j+k]; k ++);        }    }    void Go(char* str,int m)    {        int len=strlen(str);        for(int i=0;i<=len;i++)dat[i]=str[i]-'a'+1;        dat[len]=0;        da(dat, len + 1,m);        calHei(dat, len);    }};char str[100010],op[9];int nxt[100010];int main(){    int cas;scanf("%d",&cas);    int T=0;    while(cas--)    {        scanf("%s%s",op,str);        int len=strlen(str);        SA::Go(str,33);        int last=len;        for(int i=len-1;i>=0;i--)        {            if(str[i]==op[0])last=i;            nxt[i]=last;        }        ll ans=0;        for(int i=1;i<=len;i++)ans+=len-max(SA::sa[i]+SA::hei[i],nxt[SA::sa[i]]);        printf("Case #%d: %I64d\n",++T,ans);     }}/*i   rk  sa hei0   3   9   0   1   6   6   0   abc2   9   3   3   abcabc3   2   0   6   abcabcabc4   5   7   0   bc5   8   4   2   bcabc6   1   1   5   bcabcabc7   4   8   0   c8   7   5   1   cabc9   0   2   4   cabcabc24*/
0 0
原创粉丝点击