【题解】HDU-2222 Keywords Search

题目链接:HDU-2222  或  Vjudge

简单说明:

  ac自动机的建立,其中插入过程借助了字典树,处理回溯数组(也有人称失败数组)过程是一个广搜运用了STL的队列(queue)。ac自动机的过程还在写。

  这是学习ac自动机的第一题,如果wa的话,那就要注意,字串结束标记是如何标记的了。它不能单单 记录,还要 计数。WA了好几次……

my codes:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#define set(a) memset(a,0,sizeof(a))
#define set_b(a) memset(a,false,sizeof(a))
using namespace std;
const int M=5e5+10;
const int N=1e6+10;

int tree[M][26];/**< tree[u][i]  表示节点u的i儿子的节点值 */
int ed[M];/**< 字串结束标记,运用比较灵活,本题要计数 */
int nxt[M];/**< 回溯数组 */
char s[N];/**< 文本串 */
int tot;/**< 节点数 */

struct ac_auto
{
    void pre_set()/**< 初始化 */
    {
        tot=1;
        set(ed);
        set(tree);
        set(nxt);
    }
    void build(char str[])/**< 基本插入操作 */
    {
        int len=strlen(str);
        int u=1;
        for(int i=0; i<len; i++)
        {
            int v=str[i]-‘a‘;
            if(!tree[u][v])
                tree[u][v]=++tot;
            u=tree[u][v];
        }
//    printf("%d\n",u);
        ed[u]++;
    }
    void deal_next()/**< 处理回溯数组,用了一个虚拟的零号节点,下面两行表示它的所有儿子与一号建边 */
    {
        for(int i=0; i<26; i++)
            tree[0][i]=1;
        queue<int> q;
        while(!q.empty())
            q.pop();
        nxt[1]=0;/**< 一号节点回溯到零号 */
        q.push(1);/**< 用到了零号节点,先压入 1 。如果不设零号的话,是压入 1 的所有儿子。两种,注意区别 */
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=0; i<=25; i++)
            {
                if(!tree[u][i])/**< u没有i这个儿子 */

                    tree[u][i]=tree[nxt[u]][i];
                                                  /** \brief u 与它的i 儿子之间建边。有了这句话那么每个节点都将
                                                            有26个儿子,就不会存在 某节点没有 i 儿子还要继续找
                                                            父亲的回溯节点的信息这一麻烦。
                                                      \return
                                                    */
                else
                {
                    nxt[tree[u][i]]=tree[nxt[u]][i];/**< u的i儿子nxt值是next[u]的i儿子的号码 */
//                printf("nxt[%d]=%d\n",tree[u][i],tree[nxt[u]][i]);
                    q.push(tree[u][i]);
                }
//            printf("%d 的 %c 儿子编号:%d\n",u,‘a‘+i,tree[u][i]);
            }
        }
    }
    int search()
    {
        int len=strlen(s);
        int ans=0;
        int u=1,v;
        for(int i=0; i<len; i++)
        {
            v=s[i]-‘a‘;
            u=tree[u][v];
            int tp=u;
            while(tp>1&&ed[tp])
            {
                ans+=ed[tp];
                ed[tp]=0;
                tp=nxt[tp];
            }
        }
        return ans;
    }
};

int main()
{
    int T,n;
    cin>>T;
    while(T--)
    {
        ac_auto().pre_set();
        cin>>n;
        while(n--)
        {
            char str[55];
            scanf("%s",str);
            ac_auto().build(str);
        }
        scanf("%s",s);
        ac_auto().deal_next();
        int ans=ac_auto().search();
        cout<<ans<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Ycourage/p/9371230.html

时间: 2024-10-11 23:45:11

【题解】HDU-2222 Keywords Search的相关文章

HDU 2222 Keywords Search AC自动机入门题

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

HDU 2222 - Keywords Search

试个模板- - /* HDU 2222 - Keywords Search [ AC自动机 ] */ #include <bits/stdc++.h> using namespace std; const int N = 500005; const int SIZE = 26; struct Trie { int ch[N][SIZE]; int f[N], last[N], cnt[N], val[N]; int tot, ans; void init() { tot = 0; memset

HDU 2222——Keywords Search(AC自动机)

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

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

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 67950    Accepted Submission(s): 22882 Problem Description In the modern time, Search engine came into the life of everybody lik

hdu 2222 Keywords Search(ac自动机入门题)

1 /************************************************************ 2 题目: Keywords Search(hdu 2222) 3 链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 4 算法: ac自动机 5 算法思想: 多个字符串匹配,也就是相当于多个kmp 6 ***********************************************************

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(瞎搞)

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 50451    Accepted Submission(s): 16236 Problem Description In the modern time, Search engine came into the life of everybody lik

hdu 2222 Keywords Search(字典树)

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

HDU 2222 Keywords Search AC自动机

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 67122    Accepted Submission(s): 22584 Problem Description In the modern time, Search engine came into the life of everybody lik

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