分析:
首先知道求不同子串个数的做法,就是,每个后缀减去它的高度数组。这相当于一种划分,然后减去交叉部分。
这里多了一个含有字符x,求每个字符后面第一个x出现的位置,再去减去交叉部分和不含x部分的较大值即可。
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define pr(x) cout << #x << ": " << x << " "
#define pl(x) cout << #x << ": " << x << endl;
//后缀数组模板,时间复杂度nlogn,空间复杂度n
struct Suffix
{
static const int maxn = int(1e5) + 13;
int r[maxn];
//后缀数组,名词数组,高度数组(表示和它前一名后缀的最长前缀长度)。
int sa[maxn],rnk[maxn],height[maxn];
int t[maxn],t2[maxn],c[maxn],n,m;
char str[maxn];
//把string转化为r[i]
void init_string(string &s) {
n = s.size();
for(int i=0;i<n;i++) r[i]=(int)s[i];
m = 128;
}
void init_char(char *s) {
n = strlen(s);
for(int i=0; i<n; i++) r[i]=(int)s[i];
m = 128;
}
int cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; }
//处理得到后缀数组
void build() {
int i,k,p,*x=t,*y=t2;
r[n++]=0;
for (i=0; i<m; i++) c[i]=0;
for (i=0; i<n; i++) c[x[i]=r[i]]++;
for (i=1; i<m; i++) c[i]+=c[i-1];
for (i=n-1; i>=0; i--) sa[--c[x[i]]]=i;
for (k=1,p=1; k<n; k*=2,m=p) {
for (p=0,i=n-k; i<n; i++) y[p++]=i;
for (i=0; i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k;
for (i=0; i<m; i++) c[i]=0;
for (i=0; i<n; i++) c[x[y[i]]]++;
for (i=1; i<m; i++) c[i]+=c[i-1];
for (i=n-1; i>=0; i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;
x[sa[0]]=0;
for (i=1; i<n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++;
}
n--;
}
//处理得到高度数组和名次数组
void lcp() {
int i,j,k=0;
for (i=1; i<=n; i++) rnk[sa[i]]=i;
for (i=0; i<n; i++) {
if (k) k--;
j=sa[rnk[i]-1];
while (r[i+k]==r[j+k]) k++;
height[rnk[i]]=k;
}
}
}suffix;
struct jibancanyang
{
int T, dp[suffix.maxn];
char x[1], s[suffix.maxn];
void fun() {
scanf("%d", &T);
for (int cas = 1; cas <= T; ++cas) {
scanf("%s%s", x, s);
int slen = strlen(s);
dp[slen] = slen;
for (int i = slen - 1; i >= 0; --i) {
if (s[i] == x[0]) dp[i] = i;
else dp[i] = dp[i + 1];
}
suffix.init_char(s);
suffix.build();
suffix.lcp();
long long ans = 0;
for (int i = 1; i <= slen; ++i) {
ans += slen - suffix.sa[i] - max(suffix.height[i],
dp[suffix.sa[i]] - suffix.sa[i]);
}
printf("Case #%d: %lld\n", cas, ans);
}
}
}ac;
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
ac.fun();
return 0;
}