# CF 316G3 Good Substring SAM上的简单计数

### 题目大意

N,Lenti500000$N , Len_{t_i}\leq 500000$
M10$M \leq 10$

### 程序

//YxuanwKeith
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int MAXN = 6e5 + 5;

struct SAM {
int Len, Pre, Go[27];
} A[MAXN * 2];

char S[MAXN];
int N, Last, Root, tot, L[15], R[15], Ord[MAXN * 2], F[MAXN * 2][15];

void Add(int ch, int Ord) {
int np = ++ tot, p = Last;
A[np].Len = A[p].Len + 1;
if (Ord != -1) F[np][Ord] ++;
for (; p && !A[p].Go[ch]; p = A[p].Pre) A[p].Go[ch] = np;
if (!p) A[np].Pre = Root; else {
int q = A[p].Go[ch];
if (A[q].Len == A[p].Len + 1) A[np].Pre = q; else {
int nq = ++ tot;
A[nq] = A[q];
A[nq].Len = A[p].Len + 1;
A[np].Pre = A[q].Pre = nq;
for (; p && A[p].Go[ch] == q; p = A[p].Pre) A[p].Go[ch] = nq;
}
}
Last = np;
}

void Sort() {
static int tax[MAXN];
memset(tax, 0, sizeof tax);
for (int i = 1; i <= tot; i ++) tax[A[i].Len] ++;
for (int i = 1; i < MAXN; i ++) tax[i] += tax[i - 1];
for (int i = tot; i; i --) Ord[tax[A[i].Len] --] = i;
}

void Solve() {
int Ans = 0;
for (int i = tot; i; i --) {
int Now = Ord[i];
for (int j = 0; j <= N; j ++) F[A[Now].Pre][j] += F[Now][j];
if (!F[Now][0]) continue;
bool Flag = 1;
for (int j = 1; j <= N; j ++)
if (F[Now][j] < L[j] || F[Now][j] > R[j]) Flag = 0;
if (Flag) Ans += A[Now].Len - A[A[Now].Pre].Len;
}
printf("%d\n", Ans);
}

int main() {
scanf("%s", S + 1);
Root = tot = Last = 1;
for (int i = 1; i <= strlen(S + 1); i ++) Add(S[i] - 'a', 0);
}