ac自动机:
给你若干个单词,判断一段文字里边这些单词出现了吗,在哪出现,出现几次?
首先是字典树模板:

#include<bits/stdc++.h>
#define debug printf("!");
using namespace std;
const int maxn=1e3+50;
struct trie_node{
int count;
trie_node*son[26];
};
trie_node* new_node()
{
trie_node* pnode=new trie_node();
pnode->count=0;
for(int i=0;i<26;i++)pnode->son[i]=NULL;
return pnode;
}
void trie_insert(trie_node *root,char key[])
{
trie_node* node=root;
char *p=key;
while(*p)
{
if(node->son[*p-'a']==NULL)node->son[*p-'a']=new_node();
node=node->son[*p-'a'];
++p;
}
node->count+=1;
}
int trie_search(trie_node *root,char key[])
{
trie_node*node=root;
char *p=key;
while(*p&&node!=NULL)
{
node=node->son[*p-'a'];
++p;
}
if(node==NULL)return 0;
else return node->count;
}
int main()
{
int n,q,i,j;
char s[20];
trie_node *root;
root=new_node();
scanf("%d%d",&n,&q);
while(n--)
{
scanf("%s",s);
trie_insert(root,s);
}
while(q--)
{
scanf("%s",s);
printf("%d\n",trie_search(root,s));
}
}
然后是ac自动机:字典树+fail指针 重点在getfail函数
例题是 hdu5880
一整天,一直被卡MLE,改成指针形式的动态开点也卡。
然后去搜,终于搜到一篇博客。
博客说:不要一次性memset,而是,用到一个点,memset一次。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define debug printf("!");
using namespace std;
const int maxn=1e6+5;
struct T{
int fail;
int vis[26];
int dep;
}ac[maxn];
int cnt;
char s[maxn];
void init(int t)
{
ac[t].fail=ac[t].dep=0;
memset(ac[t].vis,0,sizeof(ac[t].vis));
}
inline void insert(char *s)
{
int len=strlen(s),i,p=0,dep=0;
for(i=0;i<len;i++)
{
dep++;
if(!ac[p].vis[s[i]-'a'])
{
ac[p].vis[s[i]-'a']=++cnt;
init(cnt);
}
p=ac[p].vis[s[i]-'a'];
}
ac[p].dep=dep;
}
inline void get_fail()
{
queue<int>que;
for(int i=0;i<26;i++)
{
if(ac[0].vis[i])
{
ac[ac[0].vis[i]].fail=0;
que.push(ac[0].vis[i]);
}
}
while(!que.empty())
{
int u=que.front();
que.pop();
for(int i=0;i<26;i++)
{
if(ac[u].vis[i]!=0)
{
ac[ac[u].vis[i]].fail=ac[ac[u].fail].vis[i];
que.push(ac[u].vis[i]);
}
else ac[u].vis[i]=ac[ac[u].fail].vis[i];
}
}
}
void query(char s[])
{
int len=strlen(s),i,j,k,t=0,p=0;
for(i=0;i<len;i++)
{
char c=s[i];
if('A'<=c&&c<='Z')c+=32;
else if(!('a'<=c&&c<='z'))
{
p=0;continue;
}
p=ac[p].vis[c-'a'];
for(j=p;j;j=ac[j].fail)
{
if(ac[j].dep)
{
for(k=i-ac[j].dep+1;k<=i;k++)s[k]='*';
}
}
}
}
int main()
{
int n,T;
scanf("%d",&T);
while(T--)
{
cnt=0;
init(0);
scanf("%d",&n);
while(n--)
{
scanf("%s",s);
insert(s);
}
get_fail();
getchar();
cin.getline(s,maxn);
query(s);
printf("%s\n",s);
}
}
