HDU 2222 Keywords Search (AC自动机入门题)

时间:2022-08-19 19:59:01

题意:

题解:

//先调用PreProcess()初始化
//Insert()添加串 Find()查找串
//get(char s) 返回字符s所对应的编号(考虑字符集合可能是’A’-’Z’或者”ACGT”等)
//全部Insert后调用 bfs()求fail指针

#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;

#define CN 26
#define MAXN 1000010

struct Trie
{
int next[CN];
int fail;
int cnt;
bool flag;

void init()
{
flag = true;
fail = cnt = 0;
memset(next, -1, sizeof(next));
}
} node[MAXN];

int len;

int get(char ch)
{
return ch - 'a';
}

void PreProcess()
{
len = 0;
node[0].init();
node[0].fail = -1;
}

void Insert(char *str)
{
int r = 0, i, id;
for(i = 0; str[i] != '\0'; i++)
{
id = get(str[i]);
if(node[r].next[id] == -1)
{
++len;
node[len].init();
node[r].next[id] = len;
}
r = node[r].next[id];
}
node[r].flag = false;
node[r].cnt++;
}

void BFS()
{
queue<int> q;
q.push(0);
int f, nextId, i, fail;
while(!q.empty())
{
f = q.front();
q.pop();
for(i = 0; i < CN; i++)
{
nextId = node[f].next[i];
if(nextId != -1)
{
q.push(nextId);
fail = node[f].fail;
while(fail != -1 && node[fail].next[i] == -1)
fail = node[fail].fail;
if(fail == -1)
node[nextId].fail = 0;
else
node[nextId].fail = node[fail].next[i];
}
}
}
}

int Find(char *str)
{
int ret = 0;
int r = 0, nextId, id;
for(int i = 0; str[i]; )
{
id = get(str[i]);
nextId = node[r].next[id];

if(nextId != -1)
{
int tmp = nextId;
while(tmp != 0 && node[tmp].cnt != 0)
{
ret += node[tmp].cnt;
node[tmp].cnt = 0;
tmp = node[tmp].fail;
}

r = nextId, ++i;
}
else
{
r = node[r].fail;
if(r == -1) { ++i; ++r; }
}
}
return ret;
}


int main()
{
int cs, n;
char key[100];
char desc[1000010];
scanf("%d",&cs);
while(cs--)
{
PreProcess();
scanf("%d",&n);
while(n--)
{
scanf("%s",key);
Insert(key);
}
scanf("%s",desc);
BFS();
printf("%d\n",Find(desc));
}
return 0;
}