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;
    }
  • 相关阅读:
    Atom + activate-power-mode震屏插件Windows7下安装
    通过Google身份验证器加强Linux帐户安全
    adb 常用命令总结
    excel 文件加密
    docker 进入容器命令行 /bin/bash 后不支持中文
    无法获取 gcr.io 上的镜像的解决方法
    mysql unix 时间戳转换
    docker 镜像如何导入导出以及建立自己的镜像仓库
    asp.net core 文件的处理
    docker compose 设置环境变量
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1986424.html
Copyright © 2011-2022 走看看