AC自动机模板

Description

HDU 2222 Keywords Search AC自动机模板题

给出\(n\)个模式串,和一个文本串,问文本串中一共出现了多少个模式串。

Input

第一行给出用例组数\(T\),对于每组用例,第一行给出模式串数量\(n\),接下来的\(n\)行给出\(n\)个模式串,最后一行给出一个文本串。\(n \leqslant 10000\),每个文本串最长不超过\(50\),文本串长度不超过\(1000000\)

Output

对于每组用例给出一个整数,表示文本串中包含的模式串的数量。

Sample Input

1
5
she
he
say
shr
her
yasherhs

Sample Output

3

Solution

AC自动机的构建关键在于fail边。fail边指向的结点的深度一定小于当前结点,故对trie树进行BFS,从上到下构造fail边。

  1. 初始化fail[0] = 0,fail[trie[0][i]] = 0。
  2. 设v = trie[u][x],且trie[fail[u][x]] != 0,则fail[v]=trie[fail[u]][x]。
  3. 如果trie[fail[u][x]] != 0,则找fail[fail[u]][x],直到成功或已经找到根节点。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const int INF = 0x7f7f7f7f;
const int N = 1e6 + 10;
const int M = 50 * 1e4;
const int Z = 26;

int trie[M][Z], tot, fail[M], ed[M];

int newnode()
{
    memset(trie[tot], -1, sizeof(trie[tot]));
    ed[tot] = 0;
	return tot++;
}

void init()
{
    tot = 0;
    newnode();
}

void insert(char s[])
{
	int len = strlen(s);
	int p = 0;
	for (int i = 0; i < len; i++)
	{
		int c = s[i] - 'a';
		if (trie[p][c] == -1) trie[p][c] = newnode();
		p = trie[p][c];
	}
	ed[p]++;
}

void build()
{
	queue<int> q;
	fail[0] = 0;
	for (int i = 0; i < Z; i++)
	{
		if (trie[0][i] == -1) trie[0][i] = 0;
		else fail[trie[0][i]] = 0, q.push(trie[0][i]);
	}
	while (!q.empty())
	{
		int p = q.front(); q.pop();
		for (int i = 0; i < Z; i++)
		{
			if (trie[p][i] == -1) trie[p][i] = trie[fail[p]][i];
			else fail[trie[p][i]] = trie[fail[p]][i], q.push(trie[p][i]);
		}
	}
}

int query(char s[])
{
	int len = strlen(s);
	int ans = 0, p = 0;
	for (int i = 0; i < len; i++)
	{
		p = trie[p][s[i] - 'a'];
		for (int t = p; t; t = fail[t]) ans += ed[t], ed[t] = 0;
	}
	return ans;
}

char s[N];

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		init();
		int n;
		scanf("%d", &n);
		while (n--)
		{
			scanf("%s", s);
			insert(s);
		}
		build();
		scanf("%s", &s);
		printf("%d\n", query(s));
	}
	return 0;
}

http://acm.hdu.edu.cn/showproblem.php?pid=2222

posted @ 2017-08-09 21:03  达达Mr_X  阅读(153)  评论(0编辑  收藏  举报