HDU 2222 Keywords Search【AC 自动机】


HDU 2222 Keywords Search
http://acm.hdu.edu.cn/showproblem.php?pid=2222
大意:
给出n个关键字,问在串str中出现了多少关键字。

如有5个关键字如下:

5
she
he
say
shr
her
串str = "yasherhs"

那么当前str中包含3个关键字,分别为:"she","he","her"
分析:AC 自动机

这里用的模板是根据网上修改的,
子树节点是在插入时new的,
寻找失配指针中使用的队列是用数组模拟的。

PS:第一道AC自动机,拷完别人的代码。。。。弱。。。。。。不过还是很开心O(∩_∩)O~~,继续加油↖(^ω^)↗

View Code
#include < iostream >
using namespace std;

// 子树节点是在插入时new的,
// 寻找失配指针中使用的队列是用数组模拟的
const int kind = 26 ; // 子树个数
struct node
{
node
* fail;
node
* next[kind];
int count; // 记录当前前缀是完整单词出现的个数
node()
{
fail
= NULL;
count
= 0 ;
memset(next,NULL,
sizeof (next));
}
}
* q[ 500001 ]; // 寻找失配指针时需要用到的队列

char keyword[ 51 ]; // 关键字
char str[ 100000001 ]; // 主串
void insert( char * str,node * root)
{
node
* p = root;
int i = 0 ,index;
while (str[i])
{
index
= str[i] - ' a ' ;
if (p -> next[index] == NULL)
p
-> next[index] = new node();

p
= p -> next[index];
i
++ ;
}
p
-> count ++ ;
}

// 寻找失败指针
void build_ac_automation(node * root)
{
int i;
int head,tail;
root
-> fail = NULL;
head
= 0 ;
tail
= 0 ;
q[tail
++ ] = root;
while (head != tail)
{
node
* temp = q[head ++ ]; // 取队首元素
node * p = NULL;
for (i = 0 ;i < kind;i ++ )
{
if (temp -> next[i] != NULL) // 寻找当前子树的失败指针
{
p
= temp -> fail;
while (p != NULL)
{
if (p -> next[i] != NULL) // 找到失败指针
{
temp
-> next[i] -> fail = p -> next[i];
break ;
}
p
= p -> fail;
}

if (p == NULL) // 无法获取,当前子树的失败指针为根
temp -> next[i] -> fail = root;

q[tail
++ ] = temp -> next[i]; // 当前子树入队
}
}
}
}

// 询问str中包含n个关键字中多少种
int query(node * root)
{
int i = 0 ,cnt = 0 ,index,len;
len
= strlen(str);
node
* p = root;
while (str[i])
{
index
= str[i] - ' a ' ;
while (p -> next[index] == NULL && p != root) // 失配
p = p -> fail;
p
= p -> next[index];
if (p == NULL) // 失配指针为根
p = root;

node
* temp = p;
while (temp != root && temp -> count !=- 1 ) // 标记本次过程中访问过的点
{
cnt
+= temp -> count;
temp
-> count = - 1 ;
temp
= temp -> fail;
}
i
++ ;
}

return cnt;
}
int main()
{
int n,t;
scanf(
" %d " , & t);
while (t -- )
{

node
* root = new node();
scanf(
" %d " , & n);
getchar();
while (n -- )
{
gets(keyword);
insert(keyword,root);
}

// 求失败指针
build_ac_automation(root);
scanf(
" %s " ,str);
printf(
" %d\n " ,query(root));
}
return 0 ;
}

你可能感兴趣的:(search)