您的位置:首页 > 其它

Keywords Search - HDU 2222(AC自动机模板)

2015-08-22 16:43 435 查看
题目大意:输入几个子串,然后输入一个母串,问在母串里面包含几个子串。

分析:刚学习的AC自动机,据说这是个最基础的模板题,所以也是用了最基本的写法来完成的,当然也借鉴了别人的代码思想,确实是个很神奇的东西,如果不懂KMP的话,最好先学学KMP再来学这个,会理解的更深刻一些。

代码如下:
=======================================================================================================================

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;

const int MAXN = 1e6+7;
const int MAXM = 26;
const int oo = 1e9+37;

char MumStr[MAXN];///母串

struct Ac_Trie_Node
{///Fail 失败节点
Ac_Trie_Node *Fail, *next[MAXM];
int leaf;///已这个节点为叶子节点的数目
};

void Insert(Ac_Trie_Node *root, char s[])
{///插入所有的模式串
Ac_Trie_Node *p = root;

for(int i=0; s[i]; i++)
{
int k = s[i]-'a';

if(p->next[k] == NULL)
p->next[k] = new Ac_Trie_Node();
p = p->next[k];
}

p->leaf += 1;
}
void GetFail(Ac_Trie_Node *root)
{///构造失败指针
queue<Ac_Trie_Node *> Q;
Ac_Trie_Node *p = root, *temp;

for(int i=0; i<MAXM; i++)
{
if(p->next[i] != NULL)
{
p->next[i]->Fail = root;
Q.push(p->next[i]);
}
}

while(Q.size())
{
p = Q.front();Q.pop();

for(int i=0; i<MAXM; i++) if(p->next[i])
{///如果节点p的next[i]不为空

temp = p->Fail;///查找另一个最近的next[i]不为空的地方

while(temp != NULL)
{
if(temp->next[i] != NULL)
{///查找到
p->next[i]->Fail = temp->next[i];
break;
}

temp = temp->Fail;
}

if(temp == NULL)
p->next[i]->Fail = root;

Q.push(p->next[i]);
}
}
}
void FreeTrie(Ac_Trie_Node *root)
{///释放内存
Ac_Trie_Node *p = root;

for(int i=0; i<MAXM; i++)
{
if(p->next[i] != NULL)
FreeTrie(p->next[i]);
}

free(p);
}
int Query(Ac_Trie_Node *root)
{
Ac_Trie_Node *p = root, *temp;
int sum=0;

for(int i=0; MumStr[i]; i++)
{
int k = MumStr[i]-'a';

while(!p->next[k] && p != root)
p = p->Fail;

if(!p->next[k])continue;///根节点下面没有这个字母

temp = p = p->next[k];

while(temp != root && temp->leaf != -1)
{///查找路径上的所有子节串,因为每个子串只出现一次,所以赋值为-1,防止重搜
sum += temp->leaf;
temp->leaf = -1;
temp = temp->Fail;
}
}

return sum;
}

int main()
{
int T;

scanf("%d", &T);

while(T--)
{
int M; char s[107];
Ac_Trie_Node *root = new Ac_Trie_Node();

scanf("%d", &M);

while(M--)
{
scanf("%s", s);
Insert(root, s);
}

GetFail(root);

scanf("%s", MumStr);
int ans = Query(root);

printf("%d\n", ans);

FreeTrie(root);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: