hdu 1277 AC自动机入门

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1277

推荐一篇博客(看思路就可以,实现用的是java):

https://www.cnblogs.com/nullzx/p/7499397.html

这是一道模板题,拿来练手,之前看了一篇博客,有点错误,但是hdu上面居然过了,最主要的是我在hdu上面三道AC自动机模板题都是这个错的代码,居然都过了,害的我纠结了一晚上,原来是数据太水了。

主要还是看上面的博客,写了点注释,不一定对,以后好拿来复习。

代码(指针写的):

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque>
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 10005
char str[maxn][62];
char s[62];
struct node{
    int id;//记录当前关键字的编号
    node *next[10];//指向儿子
    node *fail;//失配后指向的地方,相当于KMP里面的next数组的作用
    node(){
        id=-1;
        memset(next,0,sizeof(next));
        fail=NULL;
    }
};
queue<int>qe;//记录出现的关键字编号
queue<node*>q;//BFS
int n,m,k,t;
void insert(char *s,node *root,int ID){//插入关键字到trie里面
    node *p=root;
    int len=strlen(s);
    for(int i=0;i<len;i++){
        int id=s[i]-‘0‘;
        if(p->next[id]==NULL)
        p->next[id]=new node();
        p=p->next[id];
    }
    p->id=ID;//在关键字结束的地方把id更新为关键字的ID
}
void build_fail(node *root){//构建fail指针,要和KMP算法联想起来作比较
    while(!q.empty())
    q.pop();
    q.push(root);
    while(!q.empty()){
        node *temp=q.front();
        q.pop();
        for(int i=0;i<10;i++){
            if(temp->next[i]==NULL)
            continue;
            if(temp==root)//让root节点的所有儿子的fail指针都指向root,相当于next[0]=-1
            temp->next[i]->fail=root;
            else{
                node *p=temp->fail;//把temp->fail赋给p,因为接下来p要改变
                while(p!=NULL){//一直向fail方向走,直到找到某个点的next[i]!=NULL或者p==NULL(找不到)
                    if(p->next[i]!=NULL){
                        temp->next[i]->fail=p->next[i];
                        break;
                    }
                    p=p->fail;
                }
                if(p==NULL)//如果找不到,就让temp的儿子i的fail指针指向根
                temp->next[i]->fail=root;
            }
            q.push(temp->next[i]);
        }
    }
}
void query(node *root){
    while(!qe.empty())
    qe.pop();
    node *temp=root;
    for(int i=0;i<n;i++){
        for(int j=0;j<60;j++){
            int id=str[i][j]-‘0‘;
            //一直往fail指向的方向找,直到找到或者到了root,相当于KMP里面K一直等于next[K],最后匹配成功或者K=-1
            while(temp->next[id]==NULL&&temp!=root)
            temp=temp->fail;
            temp=temp->next[id];//temp下移
            if(temp==NULL)
            temp=root;
            node *p=temp;
            while(p!=root){//在所有的以i+‘0‘字符结尾的前缀里面找以这个字符结束的单词
                if(p->id!=-1){//注意这个p->id的位置,刚刚学,看了错的博客,把它写在了上面,hdu居然过了,纠结了我老半天
                    qe.push(p->id);
                    p->id=-1;//因为可能会有多个后缀和某一个前缀相同,可能会重复计数,所以我们要标记一下
                }
                p=p->fail;
            }
        }
    }
}
void destroy(node *root){
    if(root==NULL)
    return;
    for(int i=0;i<10;i++){
        if(root->next[i]!=NULL)
        destroy(root->next[i]);
    }
    delete root;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF){
        node *root=new node();
        for(int i=0;i<n;i++)
        scanf("%s",str[i]);
        getchar();
        char c;
        for(int i=0;i<m;i++){
            int num=0;//计算空格数量,一旦达到了三个就说明接下来开始输入关键字了
            while(num!=3&&(c=getchar())){
                if(c==‘ ‘)
                num++;
            }
            scanf("%s",s);//输入关键字
            insert(s,root,i);//把关键字插入字典树
        }
        build_fail(root);//构建fail指针
        query(root);//扫描
        if(qe.size()==0)
        printf("No key can be found !\n");
        else{
            printf("Found key:");
            while(!qe.empty()){
                printf(" [Key No. %d]",qe.front()+1);
                qe.pop();
            }
            printf("\n");
        }
        destroy(root);//释放内存
    }
    return 0;
}

原文地址:https://www.cnblogs.com/6262369sss/p/10298380.html

时间: 2024-11-08 21:39:08

hdu 1277 AC自动机入门的相关文章

HDU 2222 Keywords Search (AC自动机入门 模板)

AC自动机入门 Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.学习AC自动机之前得先有Trie树和KMP模式匹配算法的基础. AC自动机算法分为3步:1.构造一棵tire树  2.构造失败指针  3.进行模式匹配 AC自动机的优化:Trie图 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other

HDU 2222 Keywords Search AC自动机入门题

单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自动机的基础: 1 Trie, 以这个数据结构为基础的,不过增加一个fail指针和构造fail的函数 2 KMP,不是直接运用KMP,而是需要KMP的思想,KMP思想都没有的话,理解这个算法会更加吃力的. 注意本题的单词会有重复出现的,一个单词只能统计一次. 搜索了一下网上的题解,发现好多代码都是一大抄的啊,⊙﹏⊙b汗. 本博客的乃是原创代码,代码风格也是差不多固定的,转载请注明出处:http://blog.c

hdu 2222 Keywords Search(AC自动机入门)

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 42138    Accepted Submission(s): 13289 Problem Description In the modern time, Search engine came into the life of everybody like

hdu 2896 AC自动机

// hdu 2896 AC自动机 // // 题目大意: // // 给你n个短串,然后给你q串长字符串,要求每个长字符串中 // 是否出现短串,出现的短串各是什么 // // 解题思路: // // AC自动机,插入单词,构建自动机,然后查询就可以了. // // 感悟: // // 哎,自己AC自动机果然刚学,还只会个模板,自动机构没构建 // 都不知道...继续加油吧~~~FIGHTING! #include <cstdio> #include <cstring> #inc

hdu 2296 aC自动机+dp(得到价值最大的字符串)

Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3180    Accepted Submission(s): 1033 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a rom

hdu 2457 AC自动机+dp

DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2004    Accepted Submission(s): 1085 Problem Description Biologists finally invent techniques of repairing DNA that contains segments c

hdu 2825 aC自动机+状压dp

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5640    Accepted Submission(s): 1785 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

hdu 3065 AC自动机(各子串出现的次数)

病毒侵袭持续中 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10324    Accepted Submission(s): 3633 Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的“万恶之源”.这是一个庞大的病毒网站,他有着好多好多的病毒,但

hdu 5880 AC自动机

Family View Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 20 Problem Description Steam is a digital distribution platform developed by Valve Corporation offering