后缀数组
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#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
*/