ac自动机:点击打开ac自动机资料
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 500010;
struct Trie_Node
{
Trie_Node* fail;
Trie_Node* pNext[26];
int kcount;
Trie_Node()
{
fail = NULL;
kcount = 0;
memset(pNext, NULL, sizeof(pNext));
}
};
Trie_Node* proot;
Trie_Node* q[MAXN];
int head, tail;
char s1[1000010], s2[110];
void Insert_Trie(char* str)//建字典树
{
Trie_Node* p = proot;
for(; *str; str++)
{
int j = *str - 'a';
if(p->pNext[j] == NULL)
p->pNext[j] = new Trie_Node;
p = p->pNext[j];
}
p->kcount++;
}
void Build_ac_automaton_fail()//建立所有节点的失败指针
{
head = tail = 0;
proot->fail = NULL;//根节点的失败指针为空
q[tail++] = proot;//首先把根节点入队
while (head != tail)
{
Trie_Node* temp = q[head++];
Trie_Node* p = NULL;
for (int i = 0; i < 26; ++i)
{
if (temp->pNext[i] != NULL)
{
if(temp == proot)//如果temp为根节点,则其子节点的失败指针指向根节点
temp->pNext[i]->fail = proot;
else
{
p = temp->fail;//否则,p为temp的失败指针
while (p != NULL)//如果p不为空,查看其子节点p->pNext[i]是否跟temp->pNext[i]相同,仔细考虑"i"的含义
{
if (p->pNext[i] != NULL)//如果p->pNext[i]不为空
{
temp->pNext[i]->fail = p->pNext[i];//则,temp->pNext[i]的失败指针指向p->pNext[i]
break;//跳出while循环并把temp->pNext[i]进队。
}
p = p->fail;//如果p->pNext[i]为空,则p为p的失败指针
}
if(p == NULL)//如果p为空,则把p->pNext[i]的失败指针指向根节点
temp->pNext[i]->fail = proot;
}
q[tail++] = temp->pNext[i];
}
}
}
}
int Query(char* str)
{
int i = 0;
int sum = 0;
Trie_Node* p = proot;//这个p指向的是待查字符串的所查的位置,
while (str[i])
{
int j = str[i] - 'a';
while (p->pNext[j] == NULL && p != proot)//如果p是叶子节点,则把p指向p的失败指针
p = p->fail;
p = (p->pNext[j] == NULL) ? proot : p->pNext[j];//如果j所代表的字符所在的节点为空则p赋值为根节点,否则让p 为p->pNext[j]
Trie_Node* temp = p;
while (temp != proot && temp->kcount != -1)//本题只是让查出有多少单词种类,如果要查有多少单词temp->kcount != -1要删去,以及下面
{
sum += temp->kcount;
temp->kcount = -1;//如果要查有多少单词数,这一句也要删去
temp = temp->fail;
}
i++;
}
return sum;
}
int main()
{
int T;
int n;
scanf("%d", &T);
while (T--)
{
proot = new Trie_Node;
scanf("%d", &n);
while (n--)
{
scanf("%s", s2);
Insert_Trie(s2);
}
Build_ac_automaton_fail();
scanf("%s", s1);
printf("%d\n", Query(s1));
}
return 0;
}