题号不错。。。
关于 AC 自动机的知识 点我点我~~
论文里用状态机解释 AC自动机的方法太精彩了。
判断出现过多少个单词。
一个单词出现多遍只能计算一次
AC 自动机输出的时候是递归的输出的 output(u) = output(u) U output( fail(u) )
还有。。一开始就申请个大数组 和 边做边 new 的速度查不多啊
#include <stdio.h>
#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
#include <vector>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <fstream>
#include <set>
#include <stack>
using namespace std;
#define READ freopen("acm.in","r",stdin)
#define WRITE freopen("acm.out","w",stdout)
#define ll long long
#define ull unsigned long long
#define PII pair<int,int>
#define PDI pair<double,int>
#define PDD pair<double,double>
#define MII map<int,int>::iterator
#define fst first
#define sec second
#define MS(x,d) memset(x,d,sizeof(x))
#define INF 0x3f3f3f3f
#define ALL(x) x.begin(),x.end()
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ROOT 0,n-1,1
#define PB push_back
#define FOR(a,b,c) for(int a=b;a<c;a++)
#define MOD 1000000007
#define keyTree (ch[ ch[root][1] ][0])
#define MAX 200
struct Node
{
Node* next[26];
Node* fail;
bool flag;
int cnt;
Node()
{
MS(next,0);
fail=NULL;
cnt=0;
flag=false;
}
};
int top;
struct ACAutomaton
{
Node* root;
void Init()
{
top=0;
root=new Node;
root->fail=root;
}
void Insert(char *a)
{
Node* p=root;
int len=strlen(a);
for(int i=0;i<len;i++)
{
int c=a[i]-'a';
if(p->next[c]==NULL)
p->next[c]=new Node;
p=p->next[c];
}
p->cnt++;
}
void Construct()
{
queue<Node*> q;
for(int i=0;i<26;i++)
{
if(root->next[i]!=NULL)
{
root->next[i]->fail=root;
q.push(root->next[i]);
}
}
while(!q.empty())
{
Node* u=q.front();q.pop();
for(int i=0;i<26;i++)
{
Node* v=u->next[i];
if(v!=NULL)
{
q.push(v);
Node* t=u->fail;
while(t!=root&&t->next[i]==NULL)
t=t->fail;
v->fail=t->next[i]?t->next[i]:root;//Notice 先判断有没有
}
}
}
}
void del(Node *p)
{
if(p==NULL)
return ;
for(int i=0;i<26;i++)
del(p->next[i]);
delete p;
}
int solve(char *s)
{
Node* cur=root;
int ans=0;
for(int i=0;s[i];i++)
{
int id=s[i]-'a';
while(cur!=root&&cur->next[id]==NULL)
cur=cur->fail;
cur=cur->next[id]?cur->next[id]:root;// Notice
for(Node* p=cur;p!=root&&p->cnt;p=p->fail)
{
ans+=p->cnt;
p->cnt=0;
}
}
return ans;
}
}AC;
char s[1000220];
int main()
{
READ;
int cas;
scanf("%d",&cas);
while(cas--)
{
AC.Init();
int n;
char word[500];
scanf("%d",&n);
while(n--)
{
scanf("%s",word);
AC.Insert(word);
}
AC.Construct();
scanf("%s",s);
cout<<AC.solve(s)<<endl;
AC.del(AC.root);
}
return 0;
}