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


    <题目链接>

    题目大意:

    给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词。

    解题分析:

    这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非常多的时候,耗时会非常多,所以这里用到了AC自动机,这是一种类似于Trie树的数据结构,但是同时,它也用到了KMP算法中 next数组的思想。

    本题可做模板:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 5e5+5;
    int nxt[N][26],cnt[N],fail[N],pos;
    
    inline void insert(char *s){
        int now=0;
        for(int i=0;s[i];++i){
            int to=s[i]-'a';
            if(!nxt[now][to])nxt[now][to]=++pos;
            now=nxt[now][to];
        }
        ++cnt[now];
    }
    /*构造失败指针的过程概括起来就一句话:设这个节点上的字母为C,沿着他父亲的失败指针走,直到走到一个节点,他的儿
    子中也有字母为C的节点。然后把当前节点的失败指针指向那个字母也为C的儿子。如果一直走到了root都没找到,那就把失败
    指针指向root。具体操作起来只需要:先把root加入队列(root的失败指针指向自己或者NULL),这以后我们每处理一个
    点,就把它的所有儿子加入队列*/
    inline void getFail(){
        memset(fail,0,sizeof(fail));    //fail指针初始化全部指向根节点
        queue<int>q;
        for(int i=0;i<26;++i)
            if(nxt[0][i])q.push(nxt[0][i]);
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=0;i<26;++i){
                if(nxt[now][i])q.push(nxt[now][i]),fail[nxt[now][i]]=nxt[fail[now]][i];  //下一个元素的fail指针指向当前元素fail指针指向的元素对应的下一个元素
                else nxt[now][i]=nxt[fail[now]][i];
            }
        }
    }
    inline int query(char *s){
        int now=0,res=0;
        for(int i=0;s[i];i++){
            int tmp=nxt[now][s[i]-'a'];
            while(tmp){
                if(cnt[tmp]>=0){
                    res+=cnt[tmp];
                    cnt[tmp]=-1;
                }else break;
                tmp=fail[tmp];
            }
            now=nxt[now][s[i]-'a'];
        }
        return res;
    }
    char str[int(1e6+5)],s[55];
    int main(){
        int T;cin>>T;
        while(T--){
            pos=0;
            memset(nxt,0,sizeof(nxt));
            memset(cnt,0,sizeof(cnt));
            int n;scanf("%d",&n);
            while(n--){
                scanf("%s",s);
                insert(s);     //将模式串插入trie图中
            }
            getFail();
            scanf("%s",str);
            printf("%d
    ",query(str));
        }
    }
  • 相关阅读:
    第60天Shader法线贴图、切线空间
    第59天Shader基本光照模型、漫反射光照算法、光照计算、高光、灰度图实现
    第58天shader混合命令、颜色运算、顶点/片元着色、属性类型、语义、坐标空间、Unity内置矩阵、纹理采样、Cg函数
    第57天shader基本结构、渲染队列、裁剪、深度写入
    第55天XLua实现背包
    第54天XLua插件使用(续)
    第53天XLua插件使用
    第52天-lua语言基础语法
    第51天-AssetBundle(AB包)
    第50天-背包实例(三)
  • 原文地址:https://www.cnblogs.com/00isok/p/9426990.html
Copyright © 2020-2023  润新知