字符串

后缀数组

#include
#include
#include
#include
#define ll long long
using 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 hei
0   3   9   0   
1   6   6   0   abc
2   9   3   3   abcabc
3   2   0   6   abcabcabc
4   5   7   0   bc
5   8   4   2   bcabc
6   1   1   5   bcabcabc
7   4   8   0   c
8   7   5   1   cabc
9   0   2   4   cabcabc
24
*/

你可能感兴趣的:(ZYX)