SP8093 JZPGYZ - Sevenk Love Oimaster
https://www.luogu.com.cn/problem/SP8093
把模式串建SAM,然后把每个模式串扔上去跑,暴力染色,统计颜色个数(属于多少模式串)
然后询问串直接跑到对应结点输出颜色数即可
code:
#include<bits/stdc++.h>
#define ll long long
#define N 2000050
using namespace std;
struct Node {
int ch[26], fa, len;
} a[N << 1];
int tot = 1, lst = 1;
ll size[N], f[N];
void add(int c) {
int p = lst, np = ++ tot; lst = np;
a[np].len = a[p].len + 1;
for(; p && !a[p].ch[c]; p = a[p].fa) a[p].ch[c] = np;
if(!p) a[np].fa = 1;
else {
int v = a[p].ch[c];
if(a[v].len == a[p].len + 1) a[np].fa = v;
else {
int nv = ++ tot; a[nv] = a[v];
a[nv].len = a[p].len + 1;
for(; p && a[p].ch[c] == v; p = a[p].fa) a[p].ch[c] = nv;
a[np].fa = a[v].fa = nv;
}
}
}
vector<int> g[N];
long long ans = 0;
int las[N];
void dfs(int u, int id) {
// printf(" %d %d\n", u, id);
while(u && las[u] != id) {
// printf("%d ", u);
size[u] ++;
las[u] = id;
u = a[u].fa;
}
}
int m, len[N], mm;
char st[N], stt[N];
int main() {
scanf("%d%d", &m, &mm);
int sz = 0;
for(int j = 1; j <= m; j ++) {
lst = 1;
scanf("%s", st + 1);
int n = strlen(st + 1);
len[j] = n;
for(int i = 1; i <= n; i ++) add(st[i] - 'a'), stt[++ sz] = st[i];
// printf("*%d ", len[j]);
}
// for(int i = 1; i <= 20; i ++) printf("%c", stt[i]); printf("\n");
sz = 0;
for(int i = 1; i <= m; i ++)
for(int j = 1, p = 1; j <= len[i]; j ++) {
++ sz;
p = a[p].ch[stt[sz] - 'a'];
dfs(p, i);
}
while(mm --) {
scanf("%s", st + 1);
int n = strlen(st + 1), p = 1, f = 0;
for(int i = 1; i <= n; i ++) {
p = a[p].ch[st[i] - 'a'];
if(!p) {
f = 1;
break;
}
}
if(f) printf("0\n");
else printf("%d\n", size[p]);
}
return 0;
}