質問の意味:文字列と文字Xを考えると、異なるサブ文字列にXが含まれているどのように多く尋ねます
方法サブストリング異なる接尾辞配列求めて考える:$ \ sum_を{I = 1 } ^ {N}(LEN + 1-(SA [I] +高さ[I]))$は、
各iについて見ることができ、貢献すべて[i]は開始SAにサブストリング、それぞれSA [I] +高さである[I ] + 1、SA [i]が+高さ[I] + 2··· ストリングlenの終わり、それが必要なだけです区間[SA [i]は、SA [考える i]が+高さ[I]] もしそうなら、何のXは、通常の統計は、存在しない、そうでない場合は、あなたがSAを見つける必要がある[I] + [I]高さは初めての後ろに位置Xは、ここでは統計から、表示され
、それが記録位置SAの後にのみ必要である[I] Xが最初に現れる(ここで使用される次の[SA [i]は】示す)
答えは:\ [\ sum_ = {I} 1。 ^ {N}(LEN + 1 -max(SA [I] +高さ[i]は、次の[SA [I]))\]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100010;
int n;
int sa[maxn], x[maxn], c[maxn], y[maxn], height[maxn];
char s[maxn];
int near[maxn];
void SA()
{
int m = 128;
for (int i = 0; i <= m; i++)
c[i] = 0;
for (int i = 1; i <= n; i++)
c[x[i] = s[i]]++;
for (int i = 1; i <= m; i++)
c[i] += c[i - 1];
for (int i = n; i >= 1; i--)
sa[c[x[i]]--] = i;
for (int k = 1; k <= n; k <<= 1)
{
int p = 0;
for (int i = 0; i <= m; i++)
y[i] = 0;
for (int i = n - k + 1; i <= n; i++)
y[++p] = i;
for (int i = 1; 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 = 1; i <= n; i++)
c[x[y[i]]]++;
for (int i = 1; i <= m; i++)
c[i] += c[i - 1];
for (int i = n; i >= 1; i--)
sa[c[x[y[i]]]--] = y[i];
swap(x, y);
x[sa[1]] = 1;
p = 1;
for (int i = 2; i <= n; ++i)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? p : ++p;
if (p >= n)
break;
m = p;
}
}
void get_height()
{
int k = 0;
for (int i = 1; i <= n; ++i)
{
if (x[i] == 1) continue;
if (k) --k;
int j = sa[x[i] - 1];
while (j + k <= n && i + k <= n && s[i + k] == s[j + k]) ++k;
height[x[i]] = k;
}
}
int main()
{
int t;
scanf("%d", &t);
for (int tt = 1; tt <= t; tt++)
{
getchar();
char ch;
scanf("%c%s", &ch, s + 1);
n = strlen(s + 1);
SA();get_height();
memset(near, 0, sizeof(near));
for (int i = n; i >= 1; i--)
{
if (s[i] == ch)
{
int pos = i;
near[i] = i;
i--;
while (i >= 0 && s[i] != ch)
{
near[i] = pos;
i--;
}
i++;
}
}
ll ans = 0;
for (int i = 1; i <= n; i++)
{
if (near[sa[i]] == 0)
continue;
ans += n - max(near[sa[i]], sa[i] + height[i]) + 1;
}
printf("Case #%d: %lld\n", tt, ans);
}
return 0;
}