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;
}
posted @ 2021-09-06 16:00  lahlah  阅读(49)  评论(0编辑  收藏  举报