杭电 hdu 1277 全文检索


第二次


/* THE PROGRAM IS MADE BY PYY */ /*----------------------------------------------------------------------------// Copyright (c) 2011 panyanyany All rights reserved. URL : http://acm.hdu.edu.cn/showproblem.php?pid=1277 Name : hdu 1277 ( 全文检索 ) Date : Friday, August 19, 2011 Time Stage : Many hours Result: 4450219 2011-08-19 14:53:51 Accepted 1277 109MS 19256K 4903 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 60006 #define LESSMAX 10009 typedef struct tagNODE { int cnt, num ; struct tagNODE * fail, * child[10] ; } NODE ; #define root stack[0] NODE * tmp, * tmpFail, * newNode, * parntNode, * childNode ; NODE * queue[LESSMAX * 100], * stack[LESSMAX * 100] ; char model[MAXSIZE], pattn[LESSMAX] ; int m, n, num ; int head, tial ; // for queue int stkPtr ; // for stack int sequence[LESSMAX] ; // 按顺序记录能匹配的关键字序号 int iseq ; // for sequence void makeTrie () { int i, j ; int len = strlen (pattn) ; tmp = root ; for (i = 0 ; i < len ; ++i) { j = pattn[i] - '0' ; if (!tmp->child[j]) { newNode = (NODE *) calloc (1, sizeof (NODE)) ; stack[stkPtr++] = newNode ; tmp->child[j] = newNode ; } tmp = tmp->child[j] ; } tmp->num = num ; ++tmp->cnt ; } void makeFail () { int i ; head = tial = 0 ; tmp = root ; for (i = 0 ; i < 10 ; ++i) { if (tmp->child[i]) { tmp->child[i]->fail = root ; queue[tial++] = tmp->child[i] ; } } while (head < tial) { parntNode = queue[head++] ; for (i = 0 ; i < 10 ; ++i) { if (childNode = parntNode->child[i]) { tmpFail = parntNode->fail ; // 儿子的错误要从老子身上去总结 while (tmpFail && !tmpFail->child[i]) tmpFail = tmpFail->fail ; if (tmpFail) // 找到了某位祖宗跟自己同名同姓的孩子 childNode->fail = tmpFail->child[i] ; // 自己失败了就让他接着干吧 else // 找到了人类的始祖----猴子了…… childNode->fail = root ; queue[tial++] = childNode ; } } } } void ACAutomation () { int i, j ; int len = strlen (model) ; tmp = root ; for (i = 0 ; i < len ; ++i) { j = model[i] - '0' ; // 一开始的时候,用了(!tmp->child[j] && tmp) 来判断,结果只要字符失配,就出现内存访问 // 错误,因为当tmp不断向根部回溯的时候,当tmp = root ,并且tmp->child[j] == 0 的时候, // 下一句便是tmp = tmp->fail,使得tmp 指向根部的失败指针,也就是tmp = 0 ; // 然后再判断tmp->child[j] 的时候,就出现内存访问错误了。 // 于是后来改成了(tmp && !tmp->child[j]),嗯,这一句是没错了,但下一句却错了。 // tmp = (tmp->child[j]) ? tmp->child[j] : root ; 这一句也出现了上面的问题 // 我很郁闷,感觉也没有什么问题啊,无奈回头看了看以前的代码,发现原来是: // (tmp != root && !tmp->child[j]) // 这有什么不同呢?也就是说,当失败指针使tmp 指向根部时,便不再判断根部的孩子中是否 // 有匹配项了。于是有人便会问:那不就漏了一次查找了么? // 不在while循环里判断,是因为下面的一句可以判断: // tmp = (tmp->child[j]) ? tmp->child[j] : root ; // 在这里判断根部的孩子也没有匹配项之后,tmp 就正式指向根部,准备从头开始对model 中下 // 一个字符进行匹配了 // 当然了,其实这样也是可以的:while (tmp && !tmp->child[j]),不过后面的代码便不得不 // 有点啰嗦了,一段啰嗦的代码,显然不是程序员所追求的……起码现在如此≈≈≈⌒_⌒ while (tmp != root && !tmp->child[j]) // 向源头方向寻找匹配项,或者统统失配,换下一个字符 tmp = tmp->fail ; tmp = (tmp->child[j]) ? tmp->child[j] : root ; // 如果统统失配,当然要从根部重新开始了 tmpFail = tmp ; // 给tmp弄个分身,艰苦的“人口普查”工作就交给他了…… while (tmpFail->cnt) { sequence[iseq++] = tmpFail->num ; tmpFail->cnt = 0 ; tmpFail = tmpFail->fail ; } } } void recycle () { while (stkPtr) { free (stack[--stkPtr]) ; } } int main () { int i ; int len ; while (scanf ("%d%d", &m, &n) != EOF) { len = 0 ; iseq = 0 ; scanf ("%s", model) ; getchar () ; len = strlen (model) ; for (i = 1 ; i < m ; ++i) { scanf ("%s", model + len * i) ; getchar () ; } getchar () ; stkPtr = 1 ; stack[0] = (NODE *) calloc (1, sizeof (NODE)) ; for (i = 0 ; i < n ; ++i) { scanf ("[Key No. %d] %s", &num, pattn) ; // printf ("%s\n", pattn) ; getchar () ; makeTrie () ; } makeFail () ; ACAutomation () ; if (iseq) { printf ("Found key:") ; for (i = 0 ; i < iseq ; ++i) printf (" [Key No. %d]", sequence[i]) ; puts ("") ; } else puts ("No key can be found !") ; recycle () ; } return 0 ; }

第一次

/* THE PROGRAM IS MADE BY PYY */ /*----------------------------------------------------------------------------// Copyright (c) 2011 panyanyany All rights reserved. URL : http://acm.hdu.edu.cn/showproblem.php?pid=1277 Name : hdu 1277 ( 全文检索 ) Date : Friday, June 24, 2011 Time Stage : Many days Result: 4088782 2011-06-24 22:10:34 Accepted 1277 125MS 19304K 4346 B C++ pyy 4088768 2011-06-24 22:05:15 Wrong Answer 1277 0MS 240K 4218 B C++ pyy Test Data: Review: //----------------------------------------------------------------------------*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #define SZ_MODEL 60001 #define SZ_PATN 66 #define NUM_PATN 10001 #define NUM_ELEM 10 #define FIRST_ELEM ('0') typedef struct tagNODE { int cnt, id ; struct tagNODE *fail, *child[NUM_ELEM] ; } NODE ; NODE *trie[NUM_PATN * SZ_PATN], *queue[NUM_PATN * SZ_PATN], *p, *root ; char amodel[SZ_MODEL], apattern[SZ_PATN] ; int line, keyword, len, num, count, cursor, find ; // 两个数组是必须的,一个用来记录先后顺序,一个用来判断是否已经出现过 int indices[NUM_PATN], repeat[NUM_PATN] ; void initialization () { len = 0 ; cursor = 0 ; find = 0 ; trie[cursor++] = (NODE *) calloc (1, sizeof (NODE)) ; memset (repeat, 0, sizeof (repeat)) ; root = *trie ; } void recycle () { while (cursor--) { free (trie[cursor]) ; } } void makeTrie () { char *s = apattern ; int index ; p = root ; while (*s) { index = *s++ - FIRST_ELEM ; // printf ("%d ", index) ; if (! (p->child[index])) { trie[cursor] = (NODE *) calloc (1, sizeof (NODE)) ; memset (trie[cursor], 0, sizeof (trie[cursor])) ; //----------------------------- p->child[index] = trie[cursor++] ; } p = p->child[index] ; } ++p->cnt ; // 多余的变量 p->id = num ; } void makeFail () { int head, tial, i ; NODE *tmpFail ; head = tial = 0 ; // initialize index root->fail = 0 ; for (i = 0 ; i < NUM_ELEM ; ++i) { if (root->child[i]) { root->child[i]->fail = root ; queue[tial++] = root->child[i] ; } } while (head != tial) { p = queue[head++] ; for (i = 0 ; i < NUM_ELEM ; ++i) { if (p->child[i]) { queue[tial++] = p->child[i] ; // enqueue //-------------- make failure pointer----------------------- tmpFail = p->fail ; while (tmpFail) { if (tmpFail->child[i]) { p->child[i]->fail = tmpFail->child[i] ; break ; } tmpFail = tmpFail->fail ; } if (!tmpFail) p->child[i]->fail = root ; } } } } void acAutomation () { NODE *tmp ; char *s = amodel ; int index ; p = root ; while (*s) { index = *s++ - FIRST_ELEM ; while (p->child[index] == NULL && p != root) p = p->fail ; /* 此处切忌使用 p = (p == root) ? p : p->child[index] ; 这样的语句。 p 的下一个值不能通过 是否与 root 相等来判断 */ p = (p->child[index] == NULL) ? p : p->child[index] ; tmp = p ; while (tmp->id) { if (!repeat[tmp->id]) { indices[find++] = tmp->id ; repeat[tmp->id] = 1 ; } tmp->id = 0 ; tmp = tmp->fail ; } } } int main () { int i ; char c ; // freopen ("test.txt", "r", stdin) ; while (scanf ("%d%d", &line, &keyword) != EOF) { initialization () ; while (line--) { scanf ("%s%c", amodel + len, &c) ; // %c 和 c 是读取 '\n'用的, // 不能这样写 : scanf ("%s\n", amodel + len) ; 下同 len = strlen (amodel) ; } getchar () ; // 注意吸收掉一个空行 while (keyword--) { scanf ("[Key No. %d] %s%c", &num, apattern, &c) ; makeTrie () ; } makeFail () ; acAutomation () ; if (find) { printf ("Found key:") ; for (i = 0 ; i < find ; ++i) printf (" [Key No. %d]", indices[i]) ; puts ("") ; } else puts ("No key can be found !") ; recycle () ; } return 0 ; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值