CF204E Little Elephant and Strings 题解
5k_sync_closer · · 个人记录
对于一个串
于是可以双指针统计,只需要统计当前两个指针之间的子串被多少个串包含。
建广义 SAM,维护
对一个串
也就是说,我们需要对根链并加一。
把这些根链按端点 DFS 序排序,每次把一条根链的端点到它与上一条根链的端点的 LCA 这条树链加一即可。
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
struct E
{
int v, t;
} e[200050];
int T, k, n, o, z, _, __, b[200050], V[200050], l[200050], d[200050], g[200050], h[200050], f[200050][25], c[200050][26];
string u[200050];
void A(int u, int v) { e[++__] = {v, h[u]}, h[u] = __; }
void I(int x)
{
int u = ++o, p = z;
l[u] = l[z] + 1;
while (p != -1 && !c[p][x])
c[p][x] = u, p = f[p][0];
if (p == -1)
f[u][0] = 0;
else
{
int q = c[p][x];
if (l[p] + 1 == l[q])
f[u][0] = q;
else
{
int w = ++o;
l[w] = l[p] + 1;
f[w][0] = f[q][0];
for (int i = 0; i < 26; ++i)
c[w][i] = c[q][i];
while (p != -1 && c[p][x] == q)
c[p][x] = w, p = f[p][0];
f[q][0] = f[u][0] = w;
}
}
z = u;
}
void D(int u)
{
b[u] = ++_;
for (int i = h[u], v; i; i = e[i].t)
{
d[v = e[i].v] = d[u] + 1;
for (int j = 1; f[v][j - 1]; ++j)
f[v][j] = f[f[v][j - 1]][j - 1];
D(v);
}
}
int L(int x, int y)
{
if (d[x] < d[y])
swap(x, y);
while (d[x] > d[y])
x = f[x][__lg(d[x] - d[y])];
if (x == y)
return x;
for (int k = __lg(d[x]); k >= 0; --k)
if (f[x][k] != f[y][k])
x = f[x][k], y = f[y][k];
return f[x][0];
}
void S(int u, int k)
{
for (int i = h[u], v; i; i = e[i].t)
if ((v = e[i].v) != k)
S(v, u), V[u] += V[v];
}
bool C(int x, int y) { return b[x] < b[y]; }
int main()
{
f[0][0] = -1;
scanf("%d%d", &T, &k);
for (int i = 1; i <= T; ++i)
{
cin >> u[i];
z = 0;
for (auto j : u[i])
I(j - 'a');
}
for (int i = 1; i <= o; ++i)
A(f[i][0], i);
d[0] = 1;
D(0);
for (int i = 1; i <= T; ++i)
{
for (int j = 0, p = 0; j < u[i].length(); ++j)
p = c[p][u[i][j] - 'a'], g[j] = p;
sort(g, g + u[i].length(), C);
for (int j = 0; j < u[i].length(); ++j)
{
++V[g[j]];
if (j)
--V[L(g[j], g[j - 1])];
}
}
S(0, -1);
for (int i = 1; i <= T; ++i)
{
long long q = 0;
for (int l = 1, r = 0, p = 0; l <= u[i].length(); ++l)
{
if (r < l - 1)
r = l - 1, p = 0;
while (r < u[i].length() && V[c[p][u[i][r] - 'a']] >= k)
p = c[p][u[i][r++] - 'a'];
q += r - l + 1;
if (l <= r && r - l + 1 == ::l[f[p][0]] + 1)
p = f[p][0];
}
printf("%lld ", q);
}
return 0;
}