zoukankan      html  css  js  c++  java
  • HDU 2222 Keywords Search【AC 自动机】


    HDU 2222 Keywords Search
    http://acm.hdu.edu.cn/showproblem.php?pid=2222
    大意:
    给出n个关键字,问在串str中出现了多少关键字。

    如有5个关键字如下:

    5
    she
    he
    say
    shr
    her
    串str = "yasherhs"

    那么当前str中包含3个关键字,分别为:"she","he","her"
    分析:AC 自动机

    这里用的模板是根据网上修改的,
    子树节点是在插入时new的,
    寻找失配指针中使用的队列是用数组模拟的。

    PS:第一道AC自动机,拷完别人的代码。。。。弱。。。。。。不过还是很开心O(∩_∩)O~~,继续加油↖(^ω^)↗

    View Code
    #include<iostream>
    using namespace std;

    //子树节点是在插入时new的,
    //寻找失配指针中使用的队列是用数组模拟的
    const int kind = 26;//子树个数
    struct node
    {
    node
    *fail;
    node
    *next[kind];
    int count;//记录当前前缀是完整单词出现的个数
    node()
    {
    fail
    = NULL;
    count
    = 0;
    memset(next,NULL,
    sizeof(next));
    }
    }
    *q[500001];//寻找失配指针时需要用到的队列

    char keyword[51];//关键字
    char str[100000001];//主串
    void insert(char *str,node *root)
    {
    node
    *p=root;
    int i=0,index;
    while(str[i])
    {
    index
    = str[i]-'a';
    if(p->next[index]==NULL)
    p
    ->next[index]=new node();

    p
    =p->next[index];
    i
    ++;
    }
    p
    ->count++;
    }

    //寻找失败指针
    void build_ac_automation(node *root)
    {
    int i;
    int head,tail;
    root
    ->fail = NULL;
    head
    = 0;
    tail
    = 0;
    q[tail
    ++] = root;
    while(head!=tail)
    {
    node
    *temp = q[head++];//取队首元素
    node *p = NULL;
    for(i=0;i<kind;i++)
    {
    if(temp->next[i]!=NULL)//寻找当前子树的失败指针
    {
    p
    = temp->fail;
    while(p!=NULL)
    {
    if(p->next[i]!=NULL)//找到失败指针
    {
    temp
    ->next[i]->fail = p->next[i];
    break;
    }
    p
    = p->fail;
    }

    if(p==NULL)//无法获取,当前子树的失败指针为根
    temp->next[i]->fail = root;

    q[tail
    ++]=temp->next[i];//当前子树入队
    }
    }
    }
    }

    //询问str中包含n个关键字中多少种
    int query(node *root)
    {
    int i = 0,cnt = 0,index,len;
    len
    = strlen(str);
    node
    *p = root;
    while(str[i])
    {
    index
    = str[i]-'a';
    while(p->next[index]==NULL&&p!=root)//失配
    p=p->fail;
    p
    =p->next[index];
    if(p==NULL)//失配指针为根
    p = root;

    node
    *temp = p;
    while(temp!=root&&temp->count!=-1)//标记本次过程中访问过的点
    {
    cnt
    +=temp->count;
    temp
    ->count = -1;
    temp
    =temp->fail;
    }
    i
    ++;
    }

    return cnt;
    }
    int main()
    {
    int n,t;
    scanf(
    "%d",&t);
    while(t--)
    {

    node
    *root = new node();
    scanf(
    "%d",&n);
    getchar();
    while(n--)
    {
    gets(keyword);
    insert(keyword,root);
    }

    //求失败指针
    build_ac_automation(root);
    scanf(
    "%s",str);
    printf(
    "%d\n",query(root));
    }
    return 0;
    }
  • 相关阅读:
    C#基础知识简单梳理
    knearest neighbor
    二叉查找树的实现
    Unix/Linux 那些系统启动后的进程
    Nginx反向代理IIS
    线程漫谈——线程同步之信号量和互斥量
    BtxCMS@B.T.X 项目及界面展示 [下载]
    MVC in MFC or WTL
    HTTP HTTPS WebService
    ASP.NET WebAPI RC 竟然不支持最常用的json传参
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1986424.html
Copyright © 2011-2022 走看看