[Ybt 고급 2-5-1] 단어 검색

단어 쿼리

주제 링크 : ybt 효율적인 고급 2-5-1

일반적인 생각

많은 단어가 있고 또 다른 문장이 있습니다.
이 문장에서 몇 개의 단어가 하위 문자열로 나타 났는지 물어보십시오.

여러 데이터 세트.

아이디어

AC automata 템플릿 질문.

나는 전에 그것을 썼고 말할 것이 없습니다. 템플릿으로 이동하십시오.

——> 그렇지 않으면 시청할 수 있습니다 <——

암호

#include<queue> 
#include<cstdio>
#include<cstring>

using namespace std; 

struct Trie {
    
    
	int son[30], num, fail;
	bool use;
}tree[500001];
int T, tot, ans, n;
char c[51], s[1000001];
queue <int> q;

void csh() {
    
    
	tot = 0;
	ans = 0;
	memset(tree, 0, sizeof(tree));
}

void insert_word() {
    
    
	int size = strlen(c);
	int now = 0;
	
	for (int i = 0; i < size; i++) {
    
    
		if (!tree[now].son[c[i] - 'a']) tree[now].son[c[i] - 'a'] = ++tot;
		now = tree[now].son[c[i] - 'a'];
	}
	
	tree[now].num++;
}

void build_fail() {
    
    
	for (int i = 0; i < 26; i++)
		if (tree[0].son[i]) {
    
    
			q.push(tree[0].son[i]);
			tree[tree[0].son[i]].fail = 0;
		}
	
	while (!q.empty()) {
    
    
		int now = q.front();
		q.pop();
		
		for (int i = 0; i < 26; i++)
			if (tree[now].son[i]) {
    
    
				q.push(tree[now].son[i]);
				tree[tree[now].son[i]].fail = tree[tree[now].fail].son[i];
			}
			else tree[now].son[i] = tree[tree[now].fail].son[i];
	}
}

void get_AC() {
    
    
	int now = 0;
	int size = strlen(s);
	
	for (int i = 0; i < size; i++) {
    
    
		now = tree[now].son[s[i] - 'a'];
		
		int noww = now;
		while (noww && !tree[noww].use) {
    
    
			ans += tree[noww].num;
			tree[noww].use = 1;
			noww = tree[noww].fail;
		}
	}
} 

int main() {
    
    
	scanf("%d", &T);
	while (T--) {
    
    
		csh();
		
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) {
    
    
			scanf("%s", &c);
			insert_word(); 
		}
		scanf("%s", &s);
		
		build_fail();
		
		get_AC();
		
		printf("%d\n", ans);
	}
	
	return 0;
} 

추천

출처blog.csdn.net/weixin_43346722/article/details/114295501