HDU2222 AC自动机静态模板

本蒟蒻第一次做AC自动机好慌哦;

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

题目的意思不多说了,就是求目标串中有几个模式串。虽然很简单,但不过我还是做了很久。

关于AC自动机,有静态和动态模板两种,静态好像效率比较高,速度也较快(但为什么这道题动态快一点呢),动态好像内存需求有点大,但不过基于字典树,还是比较好写的。我觉得静态的比较好写,记起来也要简单一点。关于AC自动机,我是怎么会最简单的模板的呢?这个还是要依靠我们万能的网站B站了,我觉得B站上的算法讲得还是很不错的。

直接上代码吧:

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
const int N = 26;
const int MAXN = 500000 + 10;
struct node
{
	int next[MAXN][N], fail[MAXN], endd[MAXN];
	int root, l;
	int newnode()
	{
		for (int i = 0; i < N; i++)
			next[l][i] = 0;
		endd[l] = fail[l++] = 0;
		return l - 1;
	}
	void init()
	{
		l = 0;
		root = newnode();
	}
	void Insert(char s[])
	{
		int len = strlen(s);
		int now = root;
		for (int i = 0; i < len; i++)
		{
			if (next[now][s[i] - 'a'] == 0)
				next[now][s[i] - 'a'] = newnode();
			now = next[now][s[i] - 'a'];
		}
		endd[now]++;
	}
	void build()
	{
		queue<int>qu;
		int now = root;
		for (int i = 0; i < N; i++)
		{
			if (next[root][i])
				qu.push(next[root][i]);
		}
		while (!qu.empty())
		{
			now = qu.front();
			qu.pop();
			for (int i = 0; i < N; i++)
			{
				if (!next[now][i])
					next[now][i] = next[fail[now]][i];
				else
				{
					fail[next[now][i]] = next[fail[now]][i];
					qu.push(next[now][i]);
				}
			}
		}
	}
	int query(char s[])
	{
		int len = strlen(s);
		int now = root;
		int ret = 0;
		for (int i = 0; i < len; i++)
		{
			now = next[now][s[i] - 'a'];
			int tmp = now;
			while (tmp != root)
			{
				ret += endd[tmp];
				endd[tmp] = 0;
				tmp = fail[tmp];
			}
		}
		return ret;
	}
};
node Aho;
int T, n;
char buf[MAXN], str[MAXN * 2];
int main()
{
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d", &n);
		Aho.init();
		for (int i = 0; i < n; i++)
		{
			scanf("%s", buf);
			Aho.Insert(buf);
		}
		Aho.build();
		scanf("%s", str);
		int ans = Aho.query(str);
		printf("%d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/KXL5180/article/details/88093307