`

hdu 1277 全文检索 ac 自动机

阅读更多
好纠结啊,就是因为一个小小的错误,导致一错再错!一开始是这样写的:

p = (p == root) ? p : p->child[index] ;

我觉得跟另一种写法没什么区别啊!?但是后来想一想,区别还是有的,只不过自己看不太清楚而已~~~

 

发现网上几乎没有此题的解题报告,于是贴出来,大家共勉吧~~~

 

/* 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 


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 3341(ac自动机+状态压缩)

    hdu 3341(ac自动机+状态压缩) 题意:容易理解... 思路:首先一开始容易想到要用到dp,开设一个dp[41][41][41][41][501]的数组来解决,但是明显内存已经超出范围了,于是就想如何减少内存呢?只要知道A、T、C、G其中...

    HDU最全ac代码

    "HDU最全ac代码"这个压缩包很可能是包含了在HDU平台上解题通过的完整源代码集合,旨在帮助学习者理解和掌握各种算法,提升编程解决问题的能力。 首先,我们来了解一下ACM/ICPC比赛。这是一项全球性的编程竞赛,参赛...

    hdu2000-2014ac代码

    "AC"代表"Accepted",意味着提交的代码已经被评测系统接受,成功通过了所有测试用例。这个压缩包中的代码可能是用户在解决HDU平台上的编程题目时编写的,时间跨度从2000年至2014年。 从描述中我们可以推测,这个...

    杭电HDU2050题的ac程序

    一个十分简单的程序,能够ac杭电hdu的第2050题,无注释,简单明了

    hdu 300+ AC 代码

    HDU 300+ AC 代码集合是一个包含超过300个已通过验证的算法解决方案的资源,这些代码主要用于解决各类计算机编程竞赛中的问题。这些竞赛通常由杭州电子科技大学(HDU)主办,旨在提升参赛者的算法设计、编程和问题...

    hdu 一些简单题目 ac代码

    "AC"是编程比赛中常用的术语,代表"Accepted",意味着你的代码已经正确解决了题目所提出的问题,并通过了所有测试用例。 从提供的文件名来看,这些是针对HDU题目的C++源代码文件,具体题目编号包括1007、10071、...

    HDU ACM HDOJ 部分基础题AC代码

    【知识点详解】 本题是基于ACM(国际大学生程序设计竞赛)的一道基础题目,主要涉及大整数的加法运算。ACM竞赛中的题目往往需要...对于进一步的ACM训练,还需要学习其他数据结构和算法,例如排序、搜索、图论等。

    Hdu1000—2169部分代码

    6. **字符串处理**:KMP匹配、Z算法、后缀数组、AC自动机等。 通过分析和理解这些代码,你可以提升自己的算法思维,学习如何高效地解决问题,这对于参加ACM竞赛或者日常的编程工作都非常有益。同时,也可以借鉴代码...

    HDU 自动 AC 机(Python)

    一款 HDU OJ 的自动刷题工具,搜索来源可选用 百度搜索 / 必应搜索,支持并行以及串行查找,祝早日刷上航电首页哦~ 使用 Python 编写,执行之前你需要在同目录下创建文件 aclog.txt ,然后粘贴进你目前已经 AC 的...

    hdu 的2072,2084,2082,1170,ac代码

    这些题目包括HDU 2072、2084、2082和1170,每道题目都有其特定的解决思路和代码实现,而AC代码正是这些思路得以实现的证明。 首先,HDU 2072题要求我们处理字符串,并进行单词的计数与去重。在编程实践中,字符串...

    HDU_2010.rar_hdu 2010_hdu 20_hdu acm20

    【标题】"HDU_2010.rar"是一个压缩包文件,其中包含了与"HDU 2010"相关的资源,特别是针对"HDU ACM20"比赛的编程题目。"hdu 2010"和"hdu 20"可能是该比赛的不同简称或分类,而"hdu acm20"可能指的是该赛事的第20届...

    hdu.rar_hdu

    HDU(杭州电子科技大学在线评测系统)是一个深受程序员喜爱的在线编程练习平台,它提供了丰富的算法题目供用户挑战,帮助他们提升编程技能和算法理解能力。"hdu.rar_hdu"这个压缩包文件很可能是某位程序员整理的他在...

    HDU题目java实现

    8. **图论与树**:HDU题目中可能涉及图的遍历(深度优先搜索DFS、广度优先搜索BFS)、树的遍历(前序、中序、后序)以及最小生成树、最短路径等算法。 9. **动态规划**:这是一种优化策略,通过构建状态转移方程来...

    ACM HDU题目分类

    搜索题是 ACM HDU 题目分类中的一大类,例如,1010 搜索题,剪枝很关键;1016 经典的搜索;1026 搜索;1043 经典搜索题,八数码问题;1044 稍微有点麻烦的搜索题;1045 搜索题,可用匹配做 等等。 贪心算法 贪心...

    hdu2101解决方案

    hdu2101AC代码

    二叉搜索树练习 HDU3791

    总结来说,"二叉搜索树练习 HDU3791"是一道关于二叉搜索树操作的编程题,可能需要实现插入、删除、查找等基本操作,并通过分析`Main.java`源码来理解和解决问题。同时,可能需要借助各种工具进行调试和测试,以确保...

    HDU AC code

    4. **算法和数据结构**:HDU AC code中的代码通常会涉及到各种算法,如排序算法(冒泡排序、快速排序、归并排序等)、搜索算法(深度优先搜索、广度优先搜索、二分查找等)、动态规划、贪心策略、图论算法等。...

    hdu1010搜索算法

    杭州电子科技大学oj平台上的第1010题,是关于搜索的题目,很不错的题

    hdu1250高精度加法

    ### hdu1250高精度加法 #### 背景介绍 在计算机科学与编程竞赛中,处理大整数运算(特别是加法、减法、乘法等)是常见的需求之一。当数字的位数超过了标准数据类型(如`int`、`long`等)所能表示的最大值时,就需要...

    hdu杭电所有题目按照ac数量排序,python分析

    综上所述,通过对HDOJ平台上题目按AC数量排序的分析,不仅能够了解不同类型的题目特点,还能通过具体的Python示例代码加深对编程技术和解题策略的理解。此外,结合数据可视化和机器学习等进阶技术的应用,可以为平台...

Global site tag (gtag.js) - Google Analytics