本蒟蒻第一次做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;
}