第二次
/* 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 ;
}
分享到:
相关推荐
《杭电HDU ACM培训课件》是一份珍贵的学习资源,源自杭州电子科技大学的ACM竞赛培训课程。这些课件是官方论坛上分享的,旨在为那些积分不足无法获取资源或者对ACM编程竞赛感兴趣的初学者提供帮助。下面将详细阐述这...
一个十分简单的程序,能够ac杭电hdu的第2050题,无注释,简单明了
计算机网络复习大纲_杭电hdu.pdf
计算机网络复习大纲_杭电hdu整理.pdf
计算机网络复习大纲_杭电hdu参考.pdf
杭电ACM1005题源代码,AC了的程序,无问题……
杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU...
计算机网络是信息技术领域的重要组成部分,它涉及到数据的传输、交换和资源共享。本复习大纲主要涵盖了计算机网络的基础概念、体系结构、通信方式以及不同类型的网络。 首先,计算机网络的五层协议体系机构是理解...
【标题】:杭电ACMhdu1163 【描述】:这是一道源自杭州电子科技大学(Hangzhou Dianzi University,简称HDU)的ACM编程竞赛题目,编号为1163。这类问题通常需要参赛者利用计算机编程解决数学、逻辑或算法上的挑战,...
杭电hdu acm资料所用杭电的acm题
这份"HDU杭电 计算机网络实验报告"压缩包提供了丰富的实验材料,涵盖了多个关键的网络技术,包括交换机配置、路由协议、地址转换(NAT)、访问控制列表(ACL)以及动态主机配置协议(DHCP)等。以下是这些实验报告所...
HDU2000至2099题的题目以及AC代码(含思路) 适合刚刚接触ACM的同学哦~ emmmm凑字
【标题】"hdu.rar_HDU 1089.cpp_OJ题求和_hdu_horsekw5_杭电obj" 提供的信息是关于一个压缩文件,其中包含了一个名为 "HDU 1089.cpp" 的源代码文件,这个文件是为了解决杭州电子科技大学(Hangzhou Dianzi ...
为了方便广大没有网络的朋友.......
包含实验内容:对应实验要求上的1/2/3/5实验,分别为setName/setNice,petree输出进程,模拟shell,进程通信,文件系统。包含全部实验源代码和详尽的word实验报告。同时包含在线PTA编程题目:进程模拟,模拟进程调度...
"acm课件搜索(杭电)(HDU)"这个主题聚集了相关的学习材料,特别是针对搜索算法的讲解,旨在帮助学生快速掌握并应用这些技术。 搜索算法在ACM竞赛中扮演着至关重要的角色,常见的搜索策略包括深度优先搜索(DFS)...
在ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest,简称ICPC)中,数学是至关重要的一部分,尤其是在解决杭电(Hangzhou Dianzi University,简称HDU)的题目时。本课件"acm课件简单...