HDU2222 AC自动机 入门模板
程序员文章站
2022-06-04 12:46:58
...
HDU 222 Keywords Search
AC 自动机入门模板题
调了一下午
因为输入最后一个字符串打成了%d还有两处取反符号打错 WA了无数次
血泪史 以后要注意
AC自动机思路:
这个算法的目的:用几个给定的模式串去在一个串 T 中匹配
简单概括实现方式:
1.对所有的模式串建Trie树。
2.从根节点开始建立Fail指针。基本的逻辑如下:
buildFail(node root)
{
root->fail=NULL //将root的fail指针指向空节点
将root压入队列
node now
node temp // 用于临时存储递归寻找下一个可能的Fail节点
while 队列不为空
now=队列最前节点
for i 1 to 26 // 找 a-z 26个字母
if now节点下有i这个数字对应的字母
if 如果now是root节点
then do now下该数字的节点的Fail指向root
else
temp=now的fail指向的节点
while temp 不为空节点 //如果temp为空节点 即代表以及找回到了root
if temp节点下存在有i这个数字对应的字母
then do
now下该数字的节点的Fail指向temp节点下i这个数字对应的字母的节点
终止while循环
else temp=temp的fail指向的节点 //继续寻找 直到下次匹配成功
if while循环结束后 temp是空节点//如果temp为空节点 即代表以及找回到了root都没有找到匹配
then do now下该数字的节点的Fail指向root
将now节点下i这个数字对应的字母的节点压入队列
else continue
}
3.匹配过程:看代码吧= = = = = = = = =
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int T,n;
class Trie
{
public:
int cnt;
Trie * nxt[26],* fail;
Trie() { cnt=0; fail=NULL; memset(nxt,0,sizeof nxt); }
};
inline int getID(char t) {return t-'a';}
int len,id;Trie *p;
void insertTrie(char * pat,Trie * root)
{
len=strlen(pat);p=root;
for(register int i=0;i<len;i++)
{
id=getID(pat[i]);
if(!p->nxt[id]) p->nxt[id]=new Trie() ;
p=p->nxt[id];
}
p->cnt++;
return ;
}
queue<Trie *> q;Trie * temp;
void buildFail(Trie * root)
{
root->fail=NULL;
q.push(root);
while(!q.empty())
{
p=NULL;
temp=q.front();q.pop();
for(register int i=0;i<26;i++)
if(temp->nxt[i])
{
if(temp==root) temp->nxt[i]->fail=root;
else
{
p=temp->fail;
while(p)
{
if(p->nxt[i]) { temp->nxt[i]->fail=p->nxt[i] ; break; }
p=p->fail;
}
if(!p) temp->nxt[i]->fail=root;
}
q.push(temp->nxt[i]);
}
}
return ;
}
int ans=0;
int acMatch(char * str,Trie * root)
{
ans=0;
len=strlen(str);p=root;
for(register int i=0;i<len;i++)
{
id=getID(str[i]);
while(!p->nxt[id]&&p!=root) p=p->fail;
p=p->nxt[id];
if(p==NULL) p=root;
temp=p;
while(temp!=root&&temp->cnt!=-1)
{
ans+=temp->cnt;
temp->cnt=-1;
temp=temp->fail;
}
}
return ans;
}
void dataIn()
{
char buf[1000005];
scanf("%d",&T);
while(T--)
{
Trie *root=new Trie();
scanf("%d",&n);
for(register int i=1;i<=n;i++)
{
scanf("%s",buf);
insertTrie(buf,root);
}
buildFail(root);
scanf("%s",buf);
printf("%d\n",acMatch(buf,root));
}
}
int main()
{
dataIn();
return 0;
}