/* THE PROGRAM IS MADE BY PYY */
/*----------------------------------------------------------------------------//
Copyright (c) 2011 panyanyany All rights reserved.
URL : http://acm.hdu.edu.cn/showproblem.php?pid=2222
Name : 2222 Keywords Search
Date : Tuesday, 18 August, 2011
Time Stage : Many hours .....
Result:
4445107 2011-08-18 19:53:24 Accepted 2222 234MS 30152K 3051 B C++ pyy
Test Data:
Review:
第二次做了,感觉比第一次更容易理解了。不过还是出了很多错误
//----------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define infinity 0x7f7f7f7f
#define minus_inf 0x80808080
#define MAXSIZE 1000009
#define LESSMAX 55
typedef struct tagNODE {
// int fail ;
int cnt ;
struct tagNODE * child[26], * fail ;
} NODE ;
char model[MAXSIZE], pattn[LESSMAX] ;
int tcase, n ;
int stkPtr ; // pointer for stack
int head, tial ; // pointers for queue
int count ; // match words count
NODE * tmp, * newNode, * childNode, * parntNode ;
NODE * stack[LESSMAX * 10000], * queue[LESSMAX * 10000] ;
#define root stack[0]
void makeTrie ()
{
int i, j ;
int len = strlen (pattn) ;
tmp = stack[0] ;
for (i = 0 ; i < len ; ++i)
{
j = pattn[i] - 'a' ;
if (!tmp->child[j])
{
newNode = (NODE *) calloc (1, sizeof (NODE)) ;
stack[stkPtr++] = newNode ; // 注意1
tmp->child[j] = newNode ;
}
tmp = tmp->child[j] ;
// printf ("%c: %d, cnt: %d\n", pattn[i], tmp, tmp->cnt) ;
}
++tmp->cnt ;
// printf ("-------.%c, %d\n", pattn[i-1], tmp->cnt) ;
}
void makeFail ()
{
int i, j ;
head = tial = 0 ;
for (i = 0 ; i < 26 ; ++i)
if (root->child[i])
{
root->child[i]->fail = root ;
queue[tial++] = root->child[i] ;
}
while (head < tial)
{
parntNode = queue[head++] ;
for (i = 0 ; i < 26 ; ++i)
{
childNode = parntNode->child[i] ;
if (childNode)
{
tmp = parntNode->fail ;
while (tmp && !tmp->child[i])
tmp = tmp->fail ;
if (tmp)
childNode->fail = tmp->child[i] ;
else
childNode->fail = root ;
queue[tial++] = childNode ;
}
}
}
}
void ACAutomation ()
{
int i, j ;
int len = strlen (model) ;
NODE * tmpFail ;
tmp = root ;
for (i = 0 ; i < len ; ++i)
{
j = model[i] - 'a' ;
while (!tmp->child[j] && tmp != root)
tmp = tmp->fail ;
tmp = (tmp->child[j]) ? tmp->child[j] : tmp ;
// 在相同递减后缀并且未被匹配过的字符串间跳跃
// 并且记录cnt 值,然后清空cnt 值,表示以此
// 字符结尾的这个单词已经记录过了
// 但要注意,用来跳跃的指针变量,由于要不断地
// 改变,即通过fail 指针向根寻找,所以要另外
// 使用一个临时变量,不能直接用tmp 否则在下
// 一次的for循环就会没用了
tmpFail = tmp ;
while (tmpFail->cnt)
{
// printf ("%c\n", model[i]) ;
count += tmpFail->cnt ;
tmpFail->cnt = 0 ;
tmpFail = tmpFail->fail ;
}
}
}
void recycle ()
{
while (stkPtr)
free (stack[--stkPtr]) ;
}
int main ()
{
int i, j ;
while (scanf ("%d", &tcase) != EOF)
{
while (tcase--)
{
count = 0 ;
stkPtr = 1 ; // 如果用了0 ,在“注意1”
// 里stack[0]的值会被覆盖掉,然后不断悲剧……
stack[0] = (NODE *) calloc (1, sizeof (NODE)) ;
scanf ("%d", &n) ;
for (i = 0 ; i < n ; ++i)
{
scanf ("%s", pattn) ;
getchar () ;
makeTrie () ;
}
scanf ("%s", model) ; // 这一步经常忘
makeFail () ;
ACAutomation () ;
printf ("%d\n", count) ;
recycle () ; // 释放内存
}
}
return 0 ;
}
------------------------------------新旧世纪永恒的分割线---------------------------------------------------
纠结啊~郁闷啊~这题是所谓的 ac自动机 模版题 居然一直爆内存?!!试了我几天几十次啊!!纠结啊。悲剧啊。我对比了下人家的代码,感觉自己的数组明明开得比人家少啊!怎么还是爆了?一开始以为是用了 queue类 的问题,但后来改用静态数组,依旧爆!今天,没有办法了,全部改用 calloc 并且及时释放内存,不开结构体数组了,只开了两个结构体指针数组。好吧,辛辛苦苦,终于提交了……AC了,内牛满面啊~~~老天啊,您老人家终于肯看我一眼了么?
附上大牛的解题报告:
http://www.cppblog.com/mythit/archive/2009/07/30/80633.html
http://www.cnblogs.com/destinydesigner/archive/2009/10/15/1584191.html
http://www.dev-club.net/xiangxixinxi/22010072906013413/201102100439240.html
| 4075629 | 2011-06-18 14:40:59 | Accepted | 203MS | 30184K | C++ | |||
| 4069611 | 2011-06-14 20:10:26 | Memory Limit Exceeded | 62MS | 55052K | C++ | |||
| 4069609 | 2011-06-14 20:09:48 | Memory Limit Exceeded | 31MS | 33368K | G++ | |||
| 4069607 | 2011-06-14 20:09:32 | Memory Limit Exceeded | 62MS | 55124K | G++ | |||
| 4069605 | 2011-06-14 20:06:38 | Memory Limit Exceeded | 62MS | 55052K | C++ | |||
| 4069604 | 2011-06-14 20:05:47 | 0MS | 0K | C++ | ||||
| 4069602 | 2011-06-14 20:05:15 | Memory Limit Exceeded | 62MS | 55056K | C++ | |||
| 4069451 | 2011-06-14 18:19:49 | Runtime Error | 62MS | 6728K | C++ | |||
| 4069377 | 2011-06-14 17:27:08 | Wrong Answer | 312MS | 28464K | C++ | |||
| 4069374 | 2011-06-14 17:25:54 | Memory Limit Exceeded | 62MS | 55064K | C++ | |||
| 4069373 | 2011-06-14 17:25:42 | Memory Limit Exceeded | 62MS | 55064K | C++ | |||
| 4069368 | 2011-06-14 17:23:55 | Memory Limit Exceeded | 46MS | 55056K | G++ | |||
| 4069365 | 2011-06-14 17:21:47 | Memory Limit Exceeded | 62MS | 55056K | G++ | |||
| 4069364 | 2011-06-14 17:21:36 | Memory Limit Exceeded | 62MS | 55068K | C++ | |||
| 4069363 | 2011-06-14 17:20:12 | Memory Limit Exceeded | 62MS | 55068K | C++ |
/* THE PROGRAM IS MADE BY PYY */ /*----------------------------------------------------------------------------// Copyright (c) 2011 panyanyany All rights reserved. URL : http://acm.hdu.edu.cn/showproblem.php?pid=2222 Name : 2222 Keywords Search Date : Saturday, 18 June, 2011 Time Stage : Many days ..... Result: Test Data: Review: //----------------------------------------------------------------------------*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #define SIZE (50 * 10000 + 1) #define SIZE_OF_MODEL 1000010 typedef struct tagNODE { int cnt ; struct tagNODE *fail, *child[26] ; } NODE ; NODE *trie[SIZE], *root, *p, *queue[SIZE] ; char apattern[55], amodel[SIZE_OF_MODEL] ; int ikeyword, itcase, icount, ihead, itial, icursor ; void initial () { icursor = 0 ; icount = 0 ; root = (NODE*) calloc (1, sizeof (NODE)) ; } void recycle () { while (icursor) { free (trie[--icursor]) ; } free (root) ; } void makeTrie () { const int ciLen = strlen (apattern) ; int i, j, index ; p = root ; for (i = 0 ; i < ciLen ; ++i) { index = apattern[i] - 'a' ; if (! (p->child[index])) { trie[icursor] = (NODE *) calloc (1, sizeof (NODE)) ; p->child[index] = trie[icursor++] ; } p = p->child[index] ; } ++ p->cnt ; } void makeFail () { NODE *tmp, *tmpFail ; int i, j ; ihead = itial = 0 ; // root->fail = 0 ; for (i = 0 ; i < 26 ; ++i) { if (root->child[i]) { root->child[i]->fail = root ; queue[itial++] = root->child[i] ; } } while (ihead != itial) { tmp = queue[ihead++] ; // dequeue for (i = 0 ; i < 26 ; ++i) { if (tmp->child[i]) { queue[itial++] = tmp->child[i] ; // enqueue tmpFail = tmp->fail ; while (tmpFail) { if (tmpFail->child[i]) { tmp->child[i]->fail = tmpFail->child[i] ; break ; } tmpFail = tmpFail->fail ; } if (!tmpFail) { tmp->child[i]->fail = root ; } } } } } void acAutomation () { const int ciLen = strlen (amodel) ; int i, index ; NODE *tmp ; p = root ; i = 0 ; while (i < ciLen) { index = amodel[i] - 'a' ; while (p->child[index] == NULL && p != root) p = p->fail ; // printf ("/n1: %d/n", p->cnt) ; p = (p->child[index] == NULL) ? p : p->child[index] ; tmp = p ; while (tmp->cnt) { icount += tmp->cnt ; tmp->cnt = 0 ; tmp = tmp->fail ; // printf ("%d/t", icount) ; } ++i ; } } int main () { int i, j ; while (scanf ("%d", &itcase) != EOF) { while (itcase--) { initial () ; scanf ("%d", &ikeyword) ; while (ikeyword--) { scanf ("%s", apattern) ; makeTrie () ; } makeFail () ; scanf ("%s", amodel) ; acAutomation () ; printf ("%d/n", icount) ; recycle () ; } } return 0 ; }
AC自动机实战
本文介绍了一个AC自动机的实现案例,解决了关键词搜索问题,并详细记录了从初版代码到最终AC版本的过程。作者通过多次尝试,成功克服了内存溢出等问题。
584

被折叠的 条评论
为什么被折叠?



