题意:问给定的字符串(S)有多少个不同的子串满足不是另外给定的一组字符串(T1~Tn)中任何一个串的子串。
把T中的字符串依次拿去和S的自动机匹配。每次匹配到一个状态,更新这个状态所匹配的最大的长度p,那么这个状态所表示的子串中长度大于p的即为我们要找的。在计算答案的时候,我们还要同时更新目前状态的pre状态的p值,所以要按逆拓扑序计算总答案。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define lng long long
using namespace std;
const int maxn = 200000 + 10;
int str[maxn];
int len;
struct suffix_automaton
{
int ch[maxn][27], pre[maxn], val[maxn];
int c[maxn], top[maxn], p[maxn];
int sz, last;
void init()
{
pre[0] = -1; last = 0; sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
memset(p, 0, sizeof(p));
}
void insert(int x)
{
int p = last, np = sz++;
last = np;
memset(ch[np], 0, sizeof(ch[np]));
val[np] = val[p] + 1;
while(p != -1 && ch[p][x] == 0)
{
ch[p][x] = np;
p = pre[p];
}
if(p == -1) pre[np] = 0;
else
{
int q = ch[p][x];
if(val[q] == val[p] + 1) pre[np] = q;
else
{
int nq = sz++;
memcpy(ch[nq], ch[q], sizeof(ch[q]));
val[nq] = val[p] + 1;
pre[nq] = pre[q];
pre[q] = pre[np] = nq;
while(p != -1 && ch[p][x] == q) { ch[p][x] = nq; p = pre[p]; }
}
}
}
void update(char * s)
{
int l = 0, u = 0;
for(int i = 0; s[i]; ++i)
{
int x = s[i] - 'a';
if(ch[u][x])
{
u = ch[u][x];
l++;
}
else
{
while(u != -1 && ch[u][x] == 0) u = pre[u];
if(ch[u][x]) { l = val[u]; u = ch[u][x]; l++; }
else u = 0, l = 0;
}
p[u] = max(p[u], l);
}
}
void solve()
{
memset(c, 0, sizeof(c));
for(int i = 0; i < sz; ++i) c[val[i]] += 1;
for(int i = 1; i <= len; ++i) c[i] += c[i - 1];
for(int i = 0; i < sz; ++i) top[--c[val[i]]] = i;
lng ans = 0;
for(int i = sz - 1; i > 0; --i)
{
int u = top[i];
if(p[u] < val[u])
{
int tmp = max(p[u], val[pre[u]]);
ans += val[u] - tmp;
}
p[pre[u]] = max(p[pre[u]], p[u]);
}
printf("%I64d\n", ans);
}
}sam;
char s[maxn];
void prework()
{
int q; scanf("%d", &q);
scanf("%s", s); len = strlen(s);
sam.init();
for(int i = 0; i < len; ++i) { str[i] = s[i] - 'a'; sam.insert(str[i]); }
while(q--)
{
scanf("%s", s);
sam.update(s);
}
}
void solve()
{
sam.solve();
}
int main()
{
freopen("in.txt", "r", stdin);
int t; cin >> t;
int cc = 1;
while(t--)
{
prework();
printf("Case %d: ", cc++);
solve();
}
return 0;
}